Files
风扇滑翔翼 b92aa0358a More
2026-05-17 13:21:49 +00:00

69 lines
1.2 KiB
Go

package signal
import (
"context"
"sync"
"time"
)
type ActivityUpdater interface {
Update()
}
type ActivityTimer struct {
mu sync.Mutex
// timer will be nil if this timer is already finished
timer *time.Timer
timeout time.Duration
onTimeout func()
}
func (t *ActivityTimer) Update() {
// someone already called Update or closing, just return
if !t.mu.TryLock() {
return
}
defer t.mu.Unlock()
if t.timer != nil {
t.timer.Reset(t.timeout)
}
}
func (t *ActivityTimer) finish() {
t.mu.Lock()
defer t.mu.Unlock()
if t.timer != nil {
t.timer.Stop()
t.onTimeout()
t.timer = nil
}
}
func (t *ActivityTimer) SetTimeout(timeout time.Duration) {
if timeout == 0 {
t.finish()
return
}
t.mu.Lock()
defer t.mu.Unlock()
if t.timer != nil {
t.timeout = timeout
t.timer.Reset(timeout)
}
}
func CancelAfterInactivity(ctx context.Context, cancel context.CancelFunc, timeout time.Duration) *ActivityTimer {
activityTimer := &ActivityTimer{
timeout: timeout,
onTimeout: cancel,
}
// strange situation
if timeout == 0 {
cancel()
return activityTimer
}
activityTimer.timer = time.AfterFunc(timeout, activityTimer.finish)
return activityTimer
}