singledo.go 1.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. package singledo
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. type call[T any] struct {
  7. wg sync.WaitGroup
  8. val T
  9. err error
  10. }
  11. type Single[T any] struct {
  12. mux sync.Mutex
  13. last time.Time
  14. wait time.Duration
  15. call *call[T]
  16. result *Result[T]
  17. }
  18. type Result[T any] struct {
  19. Val T
  20. Err error
  21. }
  22. // Do single.Do likes sync.singleFlight
  23. func (s *Single[T]) Do(fn func() (T, error)) (v T, err error, shared bool) {
  24. s.mux.Lock()
  25. now := time.Now()
  26. if now.Before(s.last.Add(s.wait)) {
  27. s.mux.Unlock()
  28. return s.result.Val, s.result.Err, true
  29. }
  30. if callM := s.call; callM != nil {
  31. s.mux.Unlock()
  32. callM.wg.Wait()
  33. return callM.val, callM.err, true
  34. }
  35. callM := &call[T]{}
  36. callM.wg.Add(1)
  37. s.call = callM
  38. s.mux.Unlock()
  39. callM.val, callM.err = fn()
  40. callM.wg.Done()
  41. s.mux.Lock()
  42. s.call = nil
  43. s.result = &Result[T]{callM.val, callM.err}
  44. s.last = now
  45. s.mux.Unlock()
  46. return callM.val, callM.err, false
  47. }
  48. func (s *Single[T]) Reset() {
  49. s.last = time.Time{}
  50. }
  51. func NewSingle[T any](wait time.Duration) *Single[T] {
  52. return &Single[T]{wait: wait}
  53. }