blob: 60bd066d049efb5ef2f1a2a93b89e671f78ec402 [file] [log] [blame]
// Copyright 2011, 2012, 2013 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package utils
import (
"fmt"
)
type empty struct{}
type limiter chan empty
// Limiter represents a limited resource (eg a semaphore).
type Limiter interface {
// Acquire another unit of the resource.
// Acquire returns false to indicate there is no more availability,
// until another entity calls Release.
Acquire() bool
// AcquireWait requests a unit of resource, but blocks until one is
// available.
AcquireWait()
// Release returns a unit of the resource. Calling Release when there
// are no units Acquired is an error.
Release() error
}
func NewLimiter(max int) Limiter {
return make(limiter, max)
}
// Acquire requests some resources that you can return later
// It returns 'true' if there are resources available, but false if they are
// not. Callers are responsible for calling Release if this returns true, but
// should not release if this returns false.
func (l limiter) Acquire() bool {
e := empty{}
select {
case l <- e:
return true
default:
return false
}
}
// AcquireWait waits for the resource to become available before returning.
func (l limiter) AcquireWait() {
e := empty{}
l <- e
}
// Release returns the resource to the available pool.
func (l limiter) Release() error {
select {
case <-l:
return nil
default:
return fmt.Errorf("Release without an associated Acquire")
}
}