semaphore.go 751 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. package semaphore
  2. import (
  3. "context"
  4. "sync"
  5. )
  6. type Semaphore struct {
  7. sem chan struct{}
  8. }
  9. func New(n int) *Semaphore {
  10. return &Semaphore{
  11. sem: make(chan struct{}, n),
  12. }
  13. }
  14. func (s *Semaphore) Aquire(ctx context.Context) (*Token, bool) {
  15. select {
  16. case s.sem <- struct{}{}:
  17. return &Token{release: s.release}, true
  18. case <-ctx.Done():
  19. return &Token{release: func() {}}, false
  20. }
  21. }
  22. func (s *Semaphore) TryAquire() (*Token, bool) {
  23. select {
  24. case s.sem <- struct{}{}:
  25. return &Token{release: s.release}, true
  26. default:
  27. return &Token{release: func() {}}, false
  28. }
  29. }
  30. func (s *Semaphore) release() {
  31. <-s.sem
  32. }
  33. type Token struct {
  34. release func()
  35. releaseOnce sync.Once
  36. }
  37. func (t *Token) Release() {
  38. t.releaseOnce.Do(t.release)
  39. }