Skip to content
Permalink
404affda9f
Go to file
 
 
Cannot retrieve contributors at this time
75 lines (64 sloc) 1.51 KB
// Forked from github.com/StefanKopieczek/gossip by @StefanKopieczek
package util
import "sync"
// Simple semaphore implementation.
// Any number of calls to Acquire() can be made; these will not block.
// If the semaphore has been acquired more times than it has been released, it is called 'blocked'.
// Otherwise, it is called 'free'.
type Semaphore interface {
// Take a semaphore lock.
Acquire()
// Release an acquired semaphore lock.
// This should only be called when the semaphore is blocked, otherwise behaviour is undefined
Release()
// Block execution until the semaphore is free.
Wait()
// Clean up the semaphore object.
Dispose()
}
func NewSemaphore() Semaphore {
sem := new(semaphore)
sem.cond = sync.NewCond(&sync.Mutex{})
go func(s *semaphore) {
select {
case <-s.stop:
return
case <-s.acquired:
s.locks += 1
case <-s.released:
s.locks -= 1
if s.locks == 0 {
s.cond.Broadcast()
}
}
}(sem)
return sem
}
// Concrete implementation of Semaphore.
type semaphore struct {
held bool
locks int
acquired chan bool
released chan bool
stop chan bool
cond *sync.Cond
}
// Implements Semaphore.Acquire()
func (sem *semaphore) Acquire() {
sem.acquired <- true
}
// Implements Semaphore.Release()
func (sem *semaphore) Release() {
sem.released <- true
}
// Implements Semaphore.Wait()
func (sem *semaphore) Wait() {
sem.cond.L.Lock()
for sem.locks != 0 {
sem.cond.Wait()
}
}
// Implements Semaphore.Dispose()
func (sem *semaphore) Dispose() {
sem.stop <- true
}
You can’t perform that action at this time.