github.com/haraldrudell/parl@v0.4.176/periodically.go (about) 1 /* 2 © 2022–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package parl 7 8 import ( 9 "context" 10 "sync" 11 "time" 12 ) 13 14 const ( 15 defaultPeriod = time.Second 16 ) 17 18 type Periodically struct { 19 period time.Duration 20 fn func(t time.Time) 21 wg sync.WaitGroup 22 ctx context.Context 23 } 24 25 func NewPeriodically(fn func(t time.Time), ctx context.Context, period ...time.Duration) (periodically *Periodically) { 26 p := Periodically{ctx: ctx, fn: fn} 27 if len(period) > 0 { 28 p.period = period[0] 29 } 30 if p.period < defaultPeriod { 31 p.period = defaultPeriod 32 } 33 p.wg.Add(1) 34 go p.doThread() 35 return &p 36 } 37 38 func (p *Periodically) Wait() { 39 p.wg.Wait() 40 } 41 42 func (p *Periodically) doThread() { 43 defer p.wg.Done() 44 defer Recover(func() DA { return A() }, nil, Infallible) 45 46 ticker := time.NewTicker(p.period) 47 defer ticker.Stop() 48 49 done := p.ctx.Done() 50 for { 51 select { 52 case <-done: 53 return // context cancel exit 54 case t := <-ticker.C: 55 go p.doFn(t) 56 } 57 } 58 } 59 60 func (p *Periodically) doFn(t time.Time) { 61 defer Recover(func() DA { return A() }, nil, Infallible) 62 63 p.fn(t) 64 }