github.com/evdatsion/aphelion-dpos-bft@v0.32.1/libs/common/throttle_timer.go (about)

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