package timercache import ( "leafstalk/otherutils/snowflake" "log" "sync" "time" ) type CacheKeys struct { locker sync.Mutex tc *timerCache queryMap map[int64]*TimerEntry interval time.Duration msgSequence *snowflake.Node } func NewCacheKeys(d time.Duration) *CacheKeys { cache := newCache() cw := &CacheKeys{ tc: cache, queryMap: make(map[int64]*TimerEntry), interval: d, } cache.SetPrecallBack(cw.preCallBack) var err error msgSequence, err := snowflake.NewSecondNode(0, 0) if err != nil { log.Panic(err) } cw.msgSequence = msgSequence //runtime.SetFinalizer(cw, Stop) return cw } func StopCacheKeys(c *CacheKeys) { c.tc.stop <- struct{}{} } func (h *CacheKeys) preCallBack(e *TimerEntry) bool { k, ok := e.GetKey().(int64) if ok { h.locker.Lock() defer h.locker.Unlock() if _, ok := h.queryMap[k]; ok { delete(h.queryMap, k) return true } } else { log.Panicf("type convert fail %v", e.GetKey()) } return false } func (h *CacheKeys) generateMsgId() int64 { return h.msgSequence.Generate().Int64() } func (h *CacheKeys) Add(val interface{}, callBack func(e *TimerEntry), msgId int64) int64 { h.locker.Lock() defer h.locker.Unlock() if msgId == 0 { msgId = h.generateMsgId() } // k := h.generateMsgId() te := h.tc.Add(h.interval, msgId, val, callBack) h.queryMap[msgId] = te return msgId } func (h *CacheKeys) Remove(key int64) interface{} { h.locker.Lock() defer h.locker.Unlock() if v, ok := h.queryMap[key]; ok { val := v.GetVal() delete(h.queryMap, key) h.tc.Remove(v) return val } return nil } // func (h *CacheKeys) RemoveKey(key int64) { // delete(h.queryMap, key) // } type CustomCacheKeys struct { locker sync.Mutex tc *timerCache queryMap map[string]*TimerEntry Interval time.Duration } func NewCustomKeys(d time.Duration) *CustomCacheKeys { cache := newCache() cw := &CustomCacheKeys{ tc: cache, queryMap: make(map[string]*TimerEntry), Interval: d, } cache.SetPrecallBack(cw.preCallBack) //runtime.SetFinalizer(cw, Stop) return cw } func StopCustomCacheKeys(c *CustomCacheKeys) { c.tc.stop <- struct{}{} } func (h *CustomCacheKeys) preCallBack(e *TimerEntry) bool { k, ok := e.GetKey().(string) if ok { h.locker.Lock() defer h.locker.Unlock() if _, ok := h.queryMap[k]; ok { delete(h.queryMap, k) return true } } else { log.Panicf("type convert fail %v", e.GetKey()) } return false } // Add时,如果不在queryMap中,必定不在tc中,可能正在预回调后,或完全不牵涉 // 如果在queryMap中,v处在等待到预回调前的这个阶段中 func (h *CustomCacheKeys) Add(key string, val interface{}, callBack func(e *TimerEntry)) { h.locker.Lock() defer h.locker.Unlock() if v, ok := h.queryMap[key]; ok { v.SetVal(val, callBack) return } te := h.tc.Add(h.Interval, key, val, callBack) h.queryMap[key] = te } // queryMap中存在时,v处在等待到预执行前的这个阶段中 func (h *CustomCacheKeys) Remove(key string) { h.locker.Lock() defer h.locker.Unlock() if v, ok := h.queryMap[key]; ok { delete(h.queryMap, key) h.tc.Remove(v) } } // func (h *CustomCacheKeys) RemoveKey(key string) { // delete(h.queryMap, key) // }