package sync2 import "sync" type TokenPool[T any] struct { tokens []T cond *sync.Cond closed bool } func NewTokenPool[T any]() *TokenPool[T] { return &TokenPool[T]{ tokens: make([]T, 0), cond: sync.NewCond(new(sync.Mutex)), } } func NewTokenPoolWithTokens[T any](tokens ...T) *TokenPool[T] { b := NewTokenPool[T]() b.tokens = append(b.tokens, tokens...) return b } func (b *TokenPool[T]) Take() (T, bool) { b.cond.L.Lock() defer b.cond.L.Unlock() var ret T if b.closed { return ret, false } if len(b.tokens) == 0 { b.cond.Wait() if len(b.tokens) == 0 { return ret, false } } ret = b.tokens[0] b.tokens = b.tokens[1:] return ret, true } func (b *TokenPool[T]) Put(t T) { b.cond.L.Lock() b.tokens = append(b.tokens, t) b.cond.L.Unlock() b.cond.Signal() } func (b *TokenPool[T]) Close() { b.cond.L.Lock() b.closed = true b.cond.L.Unlock() b.cond.Broadcast() }