You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

semaphores.go 1.7KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. // Copyright (c) 2018 Shivaram Lingamneni
  2. // released under the MIT license
  3. package utils
  4. import (
  5. "context"
  6. "time"
  7. )
  8. // Semaphore is a counting semaphore.
  9. // A semaphore of capacity 1 can be used as a trylock.
  10. type Semaphore (chan empty)
  11. // NewSemaphore creates and initializes a semaphore to a given capacity.
  12. func NewSemaphore(capacity int) Semaphore {
  13. return make(chan empty, capacity)
  14. }
  15. // Acquire acquires a semaphore, blocking if necessary.
  16. func (semaphore Semaphore) Acquire() {
  17. semaphore <- empty{}
  18. }
  19. // TryAcquire tries to acquire a semaphore, returning whether the acquire was
  20. // successful. It never blocks.
  21. func (semaphore Semaphore) TryAcquire() (acquired bool) {
  22. select {
  23. case semaphore <- empty{}:
  24. return true
  25. default:
  26. return false
  27. }
  28. }
  29. // AcquireWithTimeout tries to acquire a semaphore, blocking for a maximum
  30. // of approximately `d` while waiting for it. It returns whether the acquire
  31. // was successful.
  32. func (semaphore Semaphore) AcquireWithTimeout(timeout time.Duration) (acquired bool) {
  33. if timeout < 0 {
  34. return semaphore.TryAcquire()
  35. }
  36. timer := time.NewTimer(timeout)
  37. select {
  38. case semaphore <- empty{}:
  39. acquired = true
  40. case <-timer.C:
  41. acquired = false
  42. }
  43. timer.Stop()
  44. return
  45. }
  46. // AcquireWithContext tries to acquire a semaphore, blocking at most until
  47. // the context expires. It returns whether the acquire was successful.
  48. // Note that if the context is already expired, the acquire may succeed anyway.
  49. func (semaphore Semaphore) AcquireWithContext(ctx context.Context) (acquired bool) {
  50. select {
  51. case semaphore <- empty{}:
  52. acquired = true
  53. case <-ctx.Done():
  54. acquired = false
  55. }
  56. return
  57. }
  58. // Release releases a semaphore.
  59. func (semaphore Semaphore) Release() {
  60. <-semaphore
  61. }