Files

69 lines
1.2 KiB
Go
Raw Permalink Normal View History

2020-11-25 19:01:53 +08:00
package signal
import (
"context"
"sync"
"time"
)
type ActivityUpdater interface {
Update()
}
type ActivityTimer struct {
2026-05-17 13:21:49 +00:00
mu sync.Mutex
// timer will be nil if this timer is already finished
timer *time.Timer
2026-05-17 20:56:19 +08:00
timeout time.Duration
2020-11-25 19:01:53 +08:00
onTimeout func()
}
func (t *ActivityTimer) Update() {
2026-05-17 13:21:49 +00:00
// someone already called Update or closing, just return
if !t.mu.TryLock() {
return
}
2026-05-17 20:56:19 +08:00
defer t.mu.Unlock()
2026-05-17 13:21:49 +00:00
if t.timer != nil {
t.timer.Reset(t.timeout)
2020-11-25 19:01:53 +08:00
}
}
func (t *ActivityTimer) finish() {
2026-05-17 13:21:49 +00:00
t.mu.Lock()
defer t.mu.Unlock()
if t.timer != nil {
t.timer.Stop()
2020-11-25 19:01:53 +08:00
t.onTimeout()
2026-05-17 13:21:49 +00:00
t.timer = nil
2026-05-17 20:56:19 +08:00
}
2020-11-25 19:01:53 +08:00
}
func (t *ActivityTimer) SetTimeout(timeout time.Duration) {
if timeout == 0 {
t.finish()
return
}
t.mu.Lock()
defer t.mu.Unlock()
2026-05-17 13:21:49 +00:00
if t.timer != nil {
2026-05-17 20:56:19 +08:00
t.timeout = timeout
2026-05-17 13:21:49 +00:00
t.timer.Reset(timeout)
}
2020-11-25 19:01:53 +08:00
}
func CancelAfterInactivity(ctx context.Context, cancel context.CancelFunc, timeout time.Duration) *ActivityTimer {
2026-05-17 20:56:19 +08:00
activityTimer := &ActivityTimer{
timeout: timeout,
2020-11-25 19:01:53 +08:00
onTimeout: cancel,
}
2026-05-17 13:21:49 +00:00
// strange situation
2026-05-17 20:56:19 +08:00
if timeout == 0 {
cancel()
return activityTimer
}
2026-05-17 13:21:49 +00:00
activityTimer.timer = time.AfterFunc(timeout, activityTimer.finish)
2026-05-17 20:56:19 +08:00
return activityTimer
2020-11-25 19:01:53 +08:00
}