Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. // Copyright (c) 2018 Shivaram Lingamneni
  2. // released under the MIT license
  3. package utils
  4. import (
  5. "log"
  6. "runtime/debug"
  7. "time"
  8. )
  9. // Semaphore is a counting semaphore. Note that a capacity of n requires O(n) storage.
  10. // A semaphore of capacity 1 can be used as a trylock.
  11. type Semaphore (chan bool)
  12. // Initialize initializes a semaphore to a given capacity.
  13. func (semaphore *Semaphore) Initialize(capacity int) {
  14. *semaphore = make(chan bool, capacity)
  15. for i := 0; i < capacity; i++ {
  16. (*semaphore) <- true
  17. }
  18. }
  19. // Acquire acquires a semaphore, blocking if necessary.
  20. func (semaphore *Semaphore) Acquire() {
  21. <-(*semaphore)
  22. }
  23. // TryAcquire tries to acquire a semaphore, returning whether the acquire was
  24. // successful. It never blocks.
  25. func (semaphore *Semaphore) TryAcquire() (acquired bool) {
  26. select {
  27. case <-(*semaphore):
  28. return true
  29. default:
  30. return false
  31. }
  32. }
  33. // AcquireWithTimeout tries to acquire a semaphore, blocking for a maximum
  34. // of approximately `d` while waiting for it. It returns whether the acquire
  35. // was successful.
  36. func (semaphore *Semaphore) AcquireWithTimeout(timeout time.Duration) (acquired bool) {
  37. if timeout < 0 {
  38. return semaphore.TryAcquire()
  39. }
  40. timer := time.NewTimer(timeout)
  41. select {
  42. case <-(*semaphore):
  43. acquired = true
  44. case <-timer.C:
  45. acquired = false
  46. }
  47. timer.Stop()
  48. return
  49. }
  50. // Release releases a semaphore. It never blocks. (This is not a license
  51. // to program spurious releases.)
  52. func (semaphore *Semaphore) Release() {
  53. select {
  54. case (*semaphore) <- true:
  55. // good
  56. default:
  57. // spurious release
  58. log.Printf("spurious semaphore release (full to capacity %d)", cap(*semaphore))
  59. debug.PrintStack()
  60. }
  61. }