Skip to content

Instantly share code, notes, and snippets.

@gorakhargosh
Created September 18, 2015 16:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gorakhargosh/efe7e8a0784a6125bd08 to your computer and use it in GitHub Desktop.
Save gorakhargosh/efe7e8a0784a6125bd08 to your computer and use it in GitHub Desktop.
interface and internal (blackbox) implementation.
// Package semaphore contains implementations of counting semaphores using both
// buffered channels and condition variables.
package semaphore
import "errors"
// Semaphore defines the protocol for any counting semaphore.
type Semaphore interface {
// Acquire blocks until a slot can be acquired in the counting semaphore.
Acquire()
// Release releases a slot in the counting semaphore.
Release()
}
const (
// SemaAcquire signals slot acquired.
SemaAcquire = iota << 1
// SemaRelease signals slot available.
SemaRelease
)
var (
// ErrCountMustBePositive is generated when an invalid count is used to
// initialize the semaphore.
ErrCountMustBePositive = errors.New("count must be greater than 0")
)
// chanSema represents a counting semaphore.
type chanSema struct {
sema chan int
}
// NewSemaphore generates a new counting semaphore. The count of the semaphore
// determines the rate at which it will throttle.
func NewSemaphore(count int) (Semaphore, error) {
if count <= 0 {
return nil, ErrCountMustBePositive
}
sema := make(chan int, count)
for i := 0; i < count; i++ {
sema <- SemaAcquire
}
return chanSema{sema}, nil
}
// Acquire blocks until a slot can be acquired in the counting semaphore.
func (sema chanSema) Acquire() {
<-sema.sema
}
// Release releases a slot in the counting semaphore.
func (sema chanSema) Release() {
sema.sema <- SemaRelease
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment