tracker.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package util
  2. import (
  3. "errors"
  4. "sync/atomic"
  5. )
  6. type StaleMode int
  7. const (
  8. BothStale StaleMode = iota
  9. EitherStale
  10. LeftStale
  11. RightStale
  12. )
  13. func (m *StaleMode) String() string {
  14. if m == nil {
  15. return "<nil>"
  16. }
  17. switch *m {
  18. case BothStale:
  19. return "both"
  20. case EitherStale:
  21. return "either"
  22. case LeftStale:
  23. return "left"
  24. case RightStale:
  25. return "right"
  26. }
  27. return "<unknown>"
  28. }
  29. func (m *StaleMode) Set(val string) error {
  30. switch val {
  31. case "both":
  32. *m = BothStale
  33. case "either":
  34. *m = EitherStale
  35. case "left":
  36. *m = LeftStale
  37. case "right":
  38. *m = RightStale
  39. default:
  40. return errors.New("unknown stale mode")
  41. }
  42. return nil
  43. }
  44. type tracker struct {
  45. leftCounter atomic.Int32
  46. rightCounter atomic.Int32
  47. leftTimedOutAt atomic.Int32
  48. rightTimedOutAt atomic.Int32
  49. staleFunc func() bool
  50. }
  51. func newTracker(staleMode StaleMode) *tracker {
  52. t := &tracker{}
  53. switch staleMode {
  54. case BothStale:
  55. t.staleFunc = t.bothStale
  56. case EitherStale:
  57. t.staleFunc = t.eitherStale
  58. case LeftStale:
  59. t.staleFunc = t.leftStale
  60. case RightStale:
  61. t.staleFunc = t.rightStale
  62. default:
  63. panic("unsupported stale mode")
  64. }
  65. return t
  66. }
  67. func (t *tracker) notify(isLeft bool) {
  68. if isLeft {
  69. t.leftCounter.Add(1)
  70. } else {
  71. t.rightCounter.Add(1)
  72. }
  73. }
  74. func (t *tracker) handleTimeout(isLeft bool) bool {
  75. if isLeft {
  76. t.leftTimedOutAt.Store(t.leftCounter.Load())
  77. } else {
  78. t.rightTimedOutAt.Store(t.rightCounter.Load())
  79. }
  80. return !t.staleFunc()
  81. }
  82. func (t *tracker) leftStale() bool {
  83. return t.leftCounter.Load() == t.leftTimedOutAt.Load()
  84. }
  85. func (t *tracker) rightStale() bool {
  86. return t.rightCounter.Load() == t.rightTimedOutAt.Load()
  87. }
  88. func (t *tracker) bothStale() bool {
  89. return t.leftStale() && t.rightStale()
  90. }
  91. func (t *tracker) eitherStale() bool {
  92. return t.leftStale() || t.rightStale()
  93. }