github.com/haraldrudell/parl@v0.4.176/counter/runners.go (about)

     1  /*
     2  © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package counter
     7  
     8  import (
     9  	"sync"
    10  	"time"
    11  
    12  	"github.com/haraldrudell/parl"
    13  	"github.com/haraldrudell/parl/perrors"
    14  	"github.com/haraldrudell/parl/ptime"
    15  )
    16  
    17  // RateRunner is a container managing threads executing rate-counter tasks by their period
    18  type RateRunner struct {
    19  	g0 parl.GoGen
    20  
    21  	lock  sync.Mutex
    22  	subGo parl.SubGo
    23  	m     map[time.Duration]*runner
    24  }
    25  
    26  // NewRateRunner returns a thread-container for running rate-counter averaging
    27  func NewRateRunner(g0 parl.GoGen) (rr *RateRunner) {
    28  	return &RateRunner{
    29  		g0: g0,
    30  		m:  map[time.Duration]*runner{},
    31  	}
    32  }
    33  
    34  // RateRunnerTask describes a rate counter
    35  type RateRunnerTask interface {
    36  	Do(at time.Time) // Do executes averaging for an accurate timestamp
    37  }
    38  
    39  // AddTask adds a new rate-counter to the container
    40  func (rr *RateRunner) AddTask(period time.Duration, task RateRunnerTask) {
    41  	rr.lock.Lock()
    42  	defer rr.lock.Unlock()
    43  
    44  	if runner, ok := rr.m[period]; ok {
    45  		runner.Add(task)
    46  		return
    47  	}
    48  
    49  	if rr.g0 == nil {
    50  		panic(perrors.NewPF("RateCounters instantiated with parl.Go nil"))
    51  	} else if rr.subGo == nil {
    52  		rr.subGo = rr.g0.SubGo()
    53  	}
    54  
    55  	runner := NewRunner()
    56  	runner.Add(task)
    57  	go ptime.OnTickerThread(runner.Do, period, time.Local, rr.subGo.Go())
    58  	rr.m[period] = runner
    59  }