github.com/vipernet-xyz/tm@v0.34.24/libs/timer/throttle_timer.go (about)

     1  package timer
     2  
     3  import (
     4  	"time"
     5  
     6  	tmsync "github.com/vipernet-xyz/tm/libs/sync"
     7  )
     8  
     9  /*
    10  ThrottleTimer fires an event at most "dur" after each .Set() call.
    11  If a short burst of .Set() calls happens, ThrottleTimer fires once.
    12  If a long continuous burst of .Set() calls happens, ThrottleTimer fires
    13  at most once every "dur".
    14  */
    15  type ThrottleTimer struct {
    16  	Name string
    17  	Ch   chan struct{}
    18  	quit chan struct{}
    19  	dur  time.Duration
    20  
    21  	mtx   tmsync.Mutex
    22  	timer *time.Timer
    23  	isSet bool
    24  }
    25  
    26  func NewThrottleTimer(name string, dur time.Duration) *ThrottleTimer {
    27  	var ch = make(chan struct{})
    28  	var quit = make(chan struct{})
    29  	var t = &ThrottleTimer{Name: name, Ch: ch, dur: dur, quit: quit}
    30  	t.mtx.Lock()
    31  	t.timer = time.AfterFunc(dur, t.fireRoutine)
    32  	t.mtx.Unlock()
    33  	t.timer.Stop()
    34  	return t
    35  }
    36  
    37  func (t *ThrottleTimer) fireRoutine() {
    38  	t.mtx.Lock()
    39  	defer t.mtx.Unlock()
    40  	select {
    41  	case t.Ch <- struct{}{}:
    42  		t.isSet = false
    43  	case <-t.quit:
    44  		// do nothing
    45  	default:
    46  		t.timer.Reset(t.dur)
    47  	}
    48  }
    49  
    50  func (t *ThrottleTimer) Set() {
    51  	t.mtx.Lock()
    52  	defer t.mtx.Unlock()
    53  	if !t.isSet {
    54  		t.isSet = true
    55  		t.timer.Reset(t.dur)
    56  	}
    57  }
    58  
    59  func (t *ThrottleTimer) Unset() {
    60  	t.mtx.Lock()
    61  	defer t.mtx.Unlock()
    62  	t.isSet = false
    63  	t.timer.Stop()
    64  }
    65  
    66  // For ease of .Stop()'ing services before .Start()'ing them,
    67  // we ignore .Stop()'s on nil ThrottleTimers
    68  func (t *ThrottleTimer) Stop() bool {
    69  	if t == nil {
    70  		return false
    71  	}
    72  	close(t.quit)
    73  	t.mtx.Lock()
    74  	defer t.mtx.Unlock()
    75  	return t.timer.Stop()
    76  }