semaphore.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. // Package semaphore implements the semaphore resiliency pattern for Go.
  2. package semaphore
  3. import (
  4. "errors"
  5. "time"
  6. )
  7. // ErrNoTickets is the error returned by Acquire when it could not acquire
  8. // a ticket from the semaphore within the configured timeout.
  9. var ErrNoTickets = errors.New("could not aquire semaphore ticket")
  10. // Semaphore implements the semaphore resiliency pattern
  11. type Semaphore struct {
  12. sem chan struct{}
  13. timeout time.Duration
  14. }
  15. // New constructs a new Semaphore with the given ticket-count
  16. // and timeout.
  17. func New(tickets int, timeout time.Duration) *Semaphore {
  18. return &Semaphore{
  19. sem: make(chan struct{}, tickets),
  20. timeout: timeout,
  21. }
  22. }
  23. // Acquire tries to acquire a ticket from the semaphore. If it can, it returns nil.
  24. // If it cannot after "timeout" amount of time, it returns ErrNoTickets. It is
  25. // safe to call Acquire concurrently on a single Semaphore.
  26. func (s *Semaphore) Acquire() error {
  27. select {
  28. case s.sem <- struct{}{}:
  29. return nil
  30. case <-time.After(s.timeout):
  31. return ErrNoTickets
  32. }
  33. }
  34. // Release releases an acquired ticket back to the semaphore. It is safe to call
  35. // Release concurrently on a single Semaphore. It is an error to call Release on
  36. // a Semaphore from which you have not first acquired a ticket.
  37. func (s *Semaphore) Release() {
  38. <-s.sem
  39. }