46 lines
850 B
Go
46 lines
850 B
Go
package sandbox
|
|
|
|
import "errors"
|
|
|
|
var ErrBusy = errors.New("busy")
|
|
|
|
// A Semaphore manages a limited number of tokens
|
|
// that can be acquired or released.
|
|
type Semaphore struct {
|
|
tokens chan struct{}
|
|
}
|
|
|
|
// NewSemaphore creates a new semaphore of the specified size.
|
|
func NewSemaphore(size int) *Semaphore {
|
|
tokens := make(chan struct{}, size)
|
|
for i := 0; i < size; i++ {
|
|
tokens <- struct{}{}
|
|
}
|
|
return &Semaphore{tokens}
|
|
}
|
|
|
|
// Acquire acquires a token. Returns ErrBusy if no tokens are available.
|
|
func (q *Semaphore) Acquire() error {
|
|
select {
|
|
case <-q.tokens:
|
|
return nil
|
|
default:
|
|
return ErrBusy
|
|
}
|
|
}
|
|
|
|
// Release releases a token.
|
|
func (q *Semaphore) Release() {
|
|
select {
|
|
case q.tokens <- struct{}{}:
|
|
return
|
|
default:
|
|
return
|
|
}
|
|
}
|
|
|
|
// Size returns the size of the semaphore.
|
|
func (q *Semaphore) Size() int {
|
|
return len(q.tokens)
|
|
}
|