timeoutlimit.go 974 B

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. package syncx
  2. import (
  3. "errors"
  4. "time"
  5. )
  6. // ErrTimeout is an error that indicates the borrow timeout.
  7. var ErrTimeout = errors.New("borrow timeout")
  8. // A TimeoutLimit is used to borrow with timeouts.
  9. type TimeoutLimit struct {
  10. limit Limit
  11. cond *Cond
  12. }
  13. // NewTimeoutLimit returns a TimeoutLimit.
  14. func NewTimeoutLimit(n int) TimeoutLimit {
  15. return TimeoutLimit{
  16. limit: NewLimit(n),
  17. cond: NewCond(),
  18. }
  19. }
  20. // Borrow borrows with given timeout.
  21. func (l TimeoutLimit) Borrow(timeout time.Duration) error {
  22. if l.TryBorrow() {
  23. return nil
  24. }
  25. var ok bool
  26. for {
  27. timeout, ok = l.cond.WaitWithTimeout(timeout)
  28. if ok && l.TryBorrow() {
  29. return nil
  30. }
  31. if timeout <= 0 {
  32. return ErrTimeout
  33. }
  34. }
  35. }
  36. // Return returns a borrow.
  37. func (l TimeoutLimit) Return() error {
  38. if err := l.limit.Return(); err != nil {
  39. return err
  40. }
  41. l.cond.Signal()
  42. return nil
  43. }
  44. // TryBorrow tries a borrow.
  45. func (l TimeoutLimit) TryBorrow() bool {
  46. return l.limit.TryBorrow()
  47. }