...
Package semaphore
Package semaphore provides a weighted semaphore implementation.
▾ Example (WorkerPool)
Example_workerPool demonstrates how to use a semaphore to limit the number of
goroutines working on parallel tasks.
This use of a semaphore mimics a typical “worker pool” pattern, but without
the need to explicitly shut down idle workers when the work is done.
Code:
package semaphore_test
import (
"context"
"fmt"
"log"
"runtime"
"golang.org/x/sync/semaphore"
)
func Example_workerPool() {
ctx := context.TODO()
var (
maxWorkers = runtime.GOMAXPROCS(0)
sem = semaphore.NewWeighted(int64(maxWorkers))
out = make([]int, 32)
)
for i := range out {
if err := sem.Acquire(ctx, 1); err != nil {
log.Printf("Failed to acquire semaphore: %v", err)
break
}
go func(i int) {
defer sem.Release(1)
out[i] = collatzSteps(i + 1)
}(i)
}
if err := sem.Acquire(ctx, int64(maxWorkers)); err != nil {
log.Printf("Failed to acquire semaphore: %v", err)
}
fmt.Println(out)
}
func collatzSteps(n int) (steps int) {
if n <= 0 {
panic("nonpositive input")
}
for ; n > 1; steps++ {
if steps < 0 {
panic("too many steps")
}
if n%2 == 0 {
n /= 2
continue
}
const maxInt = int(^uint(0) >> 1)
if n > (maxInt-1)/3 {
panic("overflow")
}
n = 3*n + 1
}
return steps
}
Weighted provides a way to bound concurrent access to a resource.
The callers can request access with a given weight.
type Weighted struct {
}
func NewWeighted(n int64) *Weighted
NewWeighted creates a new weighted semaphore with the given
maximum combined weight for concurrent access.
func (*Weighted) Acquire
¶
func (s *Weighted) Acquire(ctx context.Context, n int64) error
Acquire acquires the semaphore with a weight of n, blocking until resources
are available or ctx is done. On success, returns nil. On failure, returns
ctx.Err() and leaves the semaphore unchanged.
If ctx is already done, Acquire may still succeed without blocking.
func (*Weighted) Release
¶
func (s *Weighted) Release(n int64)
Release releases the semaphore with a weight of n.
func (s *Weighted) TryAcquire(n int64) bool
TryAcquire acquires the semaphore with a weight of n without blocking.
On success, returns true. On failure, returns false and leaves the semaphore unchanged.