package service import ( "fmt" "math" "samba/pkg/log" "sync/atomic" "time" cmap "github.com/orcaman/concurrent-map/v2" ) type timerData struct { timer *time.Timer id uint32 cb func() desc string needLog bool } type Timer struct { chTimer chan *timerData timers cmap.ConcurrentMap[uint32, *timerData] no uint32 } func NewTimer() *Timer { rt := &Timer{} rt.chTimer = make(chan *timerData, 16) rt.timers = cmap.NewWithCustomShardingFunction[uint32, *timerData](func(key uint32) uint32 { return key }) rt.no = math.MaxUint32 - 2 return rt } func (rt *Timer) NewTimer(duration time.Duration, cb func(), needLog bool, desc ...string) uint32 { tData := &timerData{ timer: nil, id: atomic.AddUint32(&rt.no, 1), cb: cb, needLog: needLog, } if len(desc) > 0 { tData.desc = desc[0] } t := time.AfterFunc(duration, func() { rt.chTimer <- tData rt.timers.Remove(tData.id) if needLog { if tData.desc != "" { log.Debug(fmt.Sprintf("移除定时器:%v NewTimer desc:%v time:%v", tData.id, tData.desc, duration)) } else { log.Debug(fmt.Sprintf("移除定时器:%v NewTimer", tData.id)) } } }) tData.timer = t rt.timers.Set(tData.id, tData) if needLog { if tData.desc != "" { log.Debug(fmt.Sprintf("设置定时器:%v NewTimer desc:%v", tData.id, tData.desc)) } else { log.Debug(fmt.Sprintf("设置定时器:%v NewTimer", tData.id)) } } return tData.id } func (rt *Timer) CancelTimer(timerId uint32) { if t, _ := rt.timers.Get(timerId); t != nil { if t.timer != nil { _ = t.timer.Stop() } rt.timers.Remove(timerId) if t.needLog { if t.desc != "" { log.Debug(fmt.Sprintf("移除定时器:%v CancelTimer desc:%v", t.id, t.desc)) } else { log.Debug(fmt.Sprintf("移除定时器:%v CancelTimer", t.id)) } } } } func (rt *Timer) CancelAllTimer() { rt.timers.IterCb(func(_ uint32, t *timerData) { if t.timer != nil { t.timer.Stop() if t.needLog { if t.desc != "" { log.Debug(fmt.Sprintf("移除定时器:%v CancelAllTimer desc:%v", t.id, t.desc)) } else { log.Debug(fmt.Sprintf("移除定时器:%v CancelAllTimer", t.id)) } } } }) rt.timers.Clear() } func (rt *Timer) GetChan() <-chan *timerData { return rt.chTimer } func (rt *Timer) Close() { close(rt.chTimer) }