|
|
|
@@ -0,0 +1,60 @@ |
|
|
|
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() |
|
|
|
} |