timer.go 1.2 KB

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