timer.go 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. package fasthttp
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. func initTimer(t *time.Timer, timeout time.Duration) *time.Timer {
  7. if t == nil {
  8. return time.NewTimer(timeout)
  9. }
  10. if t.Reset(timeout) {
  11. panic("BUG: active timer trapped into initTimer()")
  12. }
  13. return t
  14. }
  15. func stopTimer(t *time.Timer) {
  16. if !t.Stop() {
  17. // Collect possibly added time from the channel
  18. // if timer has been stopped and nobody collected its' value.
  19. select {
  20. case <-t.C:
  21. default:
  22. }
  23. }
  24. }
  25. // AcquireTimer returns a time.Timer from the pool and updates it to
  26. // send the current time on its channel after at least timeout.
  27. //
  28. // The returned Timer may be returned to the pool with ReleaseTimer
  29. // when no longer needed. This allows reducing GC load.
  30. func AcquireTimer(timeout time.Duration) *time.Timer {
  31. v := timerPool.Get()
  32. if v == nil {
  33. return time.NewTimer(timeout)
  34. }
  35. t := v.(*time.Timer)
  36. initTimer(t, timeout)
  37. return t
  38. }
  39. // ReleaseTimer returns the time.Timer acquired via AcquireTimer to the pool
  40. // and prevents the Timer from firing.
  41. //
  42. // Do not access the released time.Timer or read from it's channel otherwise
  43. // data races may occur.
  44. func ReleaseTimer(t *time.Timer) {
  45. stopTimer(t)
  46. timerPool.Put(t)
  47. }
  48. var timerPool sync.Pool