github.com/mailru/activerecord@v1.12.2/pkg/iproto/syncutil/throttle.go (about)

     1  package syncutil
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  )
     7  
     8  // NewThrottle creates new Throttle with given period.
     9  func NewThrottle(p time.Duration) *Throttle {
    10  	return &Throttle{
    11  		period: p,
    12  	}
    13  }
    14  
    15  // Throttle helps to run a function only a once per given time period.
    16  type Throttle struct {
    17  	mu     sync.RWMutex
    18  	period time.Duration
    19  	last   time.Time
    20  }
    21  
    22  // Do executes fn if Throttle's last execution time is far enough in the past.
    23  func (t *Throttle) Next() (ok bool) {
    24  	now := time.Now()
    25  
    26  	t.mu.RLock()
    27  
    28  	ok = now.Sub(t.last) >= t.period
    29  	t.mu.RUnlock()
    30  
    31  	if !ok {
    32  		return
    33  	}
    34  
    35  	t.mu.Lock()
    36  
    37  	ok = now.Sub(t.last) >= t.period
    38  	if ok {
    39  		t.last = now
    40  	}
    41  
    42  	t.mu.Unlock()
    43  
    44  	return
    45  }
    46  
    47  // Reset resets the throttle timeout such that next Next() will return true.
    48  func (t *Throttle) Reset() {
    49  	t.mu.Lock()
    50  	t.last = time.Time{}
    51  	t.mu.Unlock()
    52  }
    53  
    54  // Set sets throttle point such that Next() will return true only after given
    55  // moment p.
    56  func (t *Throttle) Set(p time.Time) {
    57  	t.mu.Lock()
    58  	t.last = p.Add(-t.period)
    59  	t.mu.Unlock()
    60  }