|
|
|
|
@ -5,7 +5,10 @@ |
|
|
|
|
// Package syncs contains additional sync types and functionality.
|
|
|
|
|
package syncs |
|
|
|
|
|
|
|
|
|
import "sync/atomic" |
|
|
|
|
import ( |
|
|
|
|
"context" |
|
|
|
|
"sync/atomic" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// ClosedChan returns a channel that's already closed.
|
|
|
|
|
func ClosedChan() <-chan struct{} { return closedChan } |
|
|
|
|
@ -79,3 +82,45 @@ func (b *AtomicBool) Set(v bool) { |
|
|
|
|
func (b *AtomicBool) Get() bool { |
|
|
|
|
return atomic.LoadInt32((*int32)(b)) != 0 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Semaphore is a counting semaphore.
|
|
|
|
|
//
|
|
|
|
|
// Use NewSemaphore to create one.
|
|
|
|
|
type Semaphore struct { |
|
|
|
|
c chan struct{} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// NewSemaphore returns a semaphore with resource count n.
|
|
|
|
|
func NewSemaphore(n int) Semaphore { |
|
|
|
|
return Semaphore{c: make(chan struct{}, n)} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Acquire blocks until a resource is acquired.
|
|
|
|
|
func (s Semaphore) Acquire() { |
|
|
|
|
s.c <- struct{}{} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// AcquireContext reports whether the resource was acquired before the ctx was done.
|
|
|
|
|
func (s Semaphore) AcquireContext(ctx context.Context) bool { |
|
|
|
|
select { |
|
|
|
|
case s.c <- struct{}{}: |
|
|
|
|
return true |
|
|
|
|
case <-ctx.Done(): |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TryAcquire reports, without blocking, whether the resource was acquired.
|
|
|
|
|
func (s Semaphore) TryAcquire() bool { |
|
|
|
|
select { |
|
|
|
|
case s.c <- struct{}{}: |
|
|
|
|
return true |
|
|
|
|
default: |
|
|
|
|
return false |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Release releases a resource.
|
|
|
|
|
func (s Semaphore) Release() { |
|
|
|
|
<-s.c |
|
|
|
|
} |
|
|
|
|
|