package q5 const CONFIG_BASE_SMALL = false const TVN_BITS = 6 const TVR_BITS = 8 const TVN_SIZE = 1 << TVN_BITS const TVR_SIZE = 1 << TVR_BITS const TVN_MASK = TVN_SIZE - 1 const TVR_MASK = TVR_SIZE - 1 const ( TIMEOUT_TIMER = 0 INTERVAL_TIMER = iota ) type XTimerDestoryHandleNode struct { entry ListHead cb func() } type XTimer struct { freeTimerNum int32 freeTimerList ListHead runningTimer *XTimerList timerTick int64 getTickCount func(interface{}) int64 context interface{} cacheTimerNum int32 tv1 [TVR_SIZE]ListHead tv2 [TVN_SIZE]ListHead tv3 [TVN_SIZE]ListHead tv4 [TVN_SIZE]ListHead tv5 [TVN_SIZE]ListHead } func (this *XTimer) Init( getTickCount func(interface{}) int64, context interface{}, gcTime int32, cacheTimerNum int32) { initListHeadFunc := func(head *ListHead) { head.Init(nil) } initListHeadFunc(&this.freeTimerList) for i := 0; i < len(this.tv1); i++ { initListHeadFunc(&this.tv1[i]) } for i := 0; i < len(this.tv2); i++ { initListHeadFunc(&this.tv2[i]) } for i := 0; i < len(this.tv3); i++ { initListHeadFunc(&this.tv3[i]) } for i := 0; i < len(this.tv4); i++ { initListHeadFunc(&this.tv4[i]) } for i := 0; i < len(this.tv5); i++ { initListHeadFunc(&this.tv5[i]) } this.timerTick = getTickCount(context) this.context = context this.getTickCount = getTickCount this.cacheTimerNum = cacheTimerNum this.SetInterval(gcTime, this.gcTimerFunc) } func (this *XTimer) UnInit() { this.clear() } func (this *XTimer) clear() { freeTimerFunc := func(head *ListHead) { for !head.Empty() { timerList := head.FirstEntry().(*XTimerList) this.detachTimer(timerList) if !timerList.attachEntry.Empty() { timerList.attachEntry.DelInit() } } } freeTimerFunc(&this.freeTimerList) for i := 0; i < len(this.tv1); i++ { freeTimerFunc(&this.tv1[i]) } for i := 0; i < len(this.tv2); i++ { freeTimerFunc(&this.tv2[i]) } for i := 0; i < len(this.tv3); i++ { freeTimerFunc(&this.tv3[i]) } for i := 0; i < len(this.tv4); i++ { freeTimerFunc(&this.tv4[i]) } for i := 0; i < len(this.tv5); i++ { freeTimerFunc(&this.tv5[i]) } } func (this *XTimer) Update() { for this.getTickCount(this.context) >= this.timerTick { index := uint32(this.timerTick & TVR_MASK) if index == 0 && this.cascade(&this.tv2, this.getTimerIndex(0)) == 0 && this.cascade(&this.tv3, this.getTimerIndex(1)) == 0 && this.cascade(&this.tv4, this.getTimerIndex(2)) == 0 { this.cascade(&this.tv5, this.getTimerIndex(3)) } this.timerTick++ var workList ListHead this.tv1[index].ReplaceInit(&workList) for !workList.Empty() { timer := workList.FirstEntry().(*XTimerList) this.runningTimer = timer timer.cb(TIMER_EXEC_EVENT, nil) if this.runningTimer != nil { switch this.runningTimer.timerType { case TIMEOUT_TIMER: this.internalDelete(timer, false, true) case INTERVAL_TIMER: this.internalModifyTime(timer, timer.expireTime) } } } } this.runningTimer = nil } func (this *XTimer) NewTimerAttacher() *XTimerAttacher { attacher := new(XTimerAttacher) attacher.timer = this attacher.timers.Init(nil) return attacher } func (this *XTimer) SetTimeout(expireTime int32, cb TimerCb) { this.internalSetTimeout(expireTime, cb, nil, nil) } func (this *XTimer) SetTimeoutEx(expireTime int32, cb TimerCb, attacher *XTimerAttacher) { this.internalSetTimeout(expireTime, cb, attacher, nil) } func (this *XTimer) SetTimeoutWp(expireTime int32, cb TimerCb) *XTimerWp { var wp *XTimerWp this.internalSetTimeout(expireTime, cb, nil, &wp) return wp } func (this *XTimer) SetTimeoutExWp(expireTime int32, cb TimerCb, attacher *XTimerAttacher) *XTimerWp { var wp *XTimerWp this.internalSetTimeout(expireTime, cb, attacher, &wp) return wp } func (this *XTimer) SetInterval(expireTime int32, cb TimerCb) { this.internalSetInterval(expireTime, cb, nil, nil) } func (this *XTimer) SetIntervalEx(expireTime int32, cb TimerCb, attacher *XTimerAttacher) { this.internalSetInterval(expireTime, cb, attacher, nil) } func (this *XTimer) SetIntervalWp(expireTime int32, cb TimerCb) *XTimerWp { var wp *XTimerWp this.internalSetInterval(expireTime, cb, nil, &wp) return wp } func (this *XTimer) SetIntervalExWp(expireTime int32, cb TimerCb, attacher *XTimerAttacher) *XTimerWp { var wp *XTimerWp this.internalSetInterval(expireTime, cb, attacher, &wp) return wp } func (this *XTimer) internalSetTimeout(expireTime int32, cb TimerCb, attacher *XTimerAttacher, wpPp **XTimerWp) { timer := this.newTimerList() timer.initTimerList(this, TIMEOUT_TIMER, expireTime, cb) if attacher != nil { attacher.timers.AddTail(&timer.attachEntry) } this.internalModifyTime(timer, expireTime) if wpPp != nil { timer.wp = &XTimerWp{ timer: timer, } *wpPp = timer.wp } } func (this *XTimer) internalSetInterval(expireTime int32, cb TimerCb, attacher *XTimerAttacher, wpPp **XTimerWp) { timer := this.newTimerList() timer.initTimerList(this, INTERVAL_TIMER, expireTime, cb) if attacher != nil { attacher.timers.AddTail(&timer.attachEntry) } this.internalModifyTime(timer, expireTime) if wpPp != nil { timer.wp = &XTimerWp{ timer: timer, } *wpPp = timer.wp } } func (this *XTimer) ModifyTimer(timerWp *XTimerWp, expireTime int32) { if timerWp.Expired() { panic("Xtimer ModifyTimer expired timer") } this.internalModifyTime(timerWp.timer, expireTime) } func (this *XTimer) Delete(timerWp *XTimerWp) { if timerWp.Expired() { panic("Xtimer Delete expired timer") } this.internalDelete(timerWp.timer, false, true) } func (this *XTimer) GetRemainTime(timerWp *XTimerWp) int64 { if timerWp.Expired() { panic("Xtimer GetRemainTime expired timer") } return this.internalGetRemainTime(timerWp.timer) } func (this *XTimer) internalGetRemainTime(timer *XTimerList) int64 { remainTime := timer.expires - this.getTickCount(this.context) if remainTime < 0 { return 0 } else { return remainTime } } func (this *XTimer) GetIdleTime() int64 { var idleTime int64 = 1 for i := (this.timerTick & TVR_MASK); i < TVR_SIZE; i++ { if !this.tv1[i].Empty() { break } idleTime++ } return idleTime } func (this *XTimer) detachTimer(timerList *XTimerList) { if !timerList.entry.Empty() { timerList.entry.DelInit() } } func (this *XTimer) addToFreeList(timerList *XTimerList) { timerList.reset() this.freeTimerList.AddTail(&timerList.entry) this.freeTimerNum++ } func (this *XTimer) cascade(tv *[TVN_SIZE]ListHead, index uint32) uint32 { var cascadeList ListHead tv[index].ReplaceInit(&cascadeList) if !cascadeList.Empty() { pos := cascadeList.next next := pos.next for pos != &cascadeList { this.internalAddTimer(pos.data.(*XTimerList)) pos = next next = pos.next } } return index } func (this *XTimer) internalAddTimer(timerList *XTimerList) { timerList.entry.data = timerList expires := timerList.expires idx := expires - this.timerTick var vec *ListHead var index uint32 if idx < 0 { index = (uint32)(this.timerTick & TVR_MASK) vec = &this.tv1[index] } else if idx < TVR_SIZE { index = (uint32)(expires & TVR_MASK) vec = &this.tv1[index] } else if idx < (1 << (TVR_BITS + TVN_BITS)) { index = (uint32)((expires >> TVR_BITS) & TVN_MASK) vec = &this.tv2[index] } else if idx < (1 << (TVR_BITS + 2*TVN_BITS)) { index = (uint32)((expires >> (TVR_BITS + 1*TVN_BITS)) & TVN_MASK) vec = &this.tv3[index] } else if idx < (1 << (TVR_BITS + 3*TVN_BITS)) { index = (uint32)((expires >> (TVR_BITS + 2*TVN_BITS)) & TVN_MASK) vec = &this.tv4[index] } else { index = (uint32)((expires >> (TVR_BITS + 3*TVN_BITS)) & TVN_MASK) vec = &this.tv5[index] } vec.AddTail(&timerList.entry) } func (this *XTimer) getTimerIndex(index uint32) uint32 { return (uint32)((this.timerTick >> (TVR_BITS + index*TVN_BITS)) & TVN_MASK) } func (this *XTimer) newTimerList() *XTimerList { if !this.freeTimerList.Empty() { timerList := this.freeTimerList.FirstEntry().(*XTimerList) this.freeTimerNum-- return timerList } else { timerList := new(XTimerList) timerList.init() return timerList } } func (this *XTimer) gcTimerFunc(ev int32, args *Args) { if ev == TIMER_EXEC_EVENT { count := 0 for !this.freeTimerList.Empty() && this.freeTimerNum > this.cacheTimerNum { timerList := this.freeTimerList.FirstEntry().(*XTimerList) timerList.entry.DelInit() this.freeTimerNum-- count++ if count > 1000 { break } } } } func (this *XTimer) internalDelete(timer *XTimerList, isDestory bool, toFreeList bool) { if timer == nil { panic("Xtimer.internalDelete error") } if this.runningTimer == timer { this.runningTimer = nil } this.detachTimer(timer) if !timer.attachEntry.Empty() { timer.attachEntry.DelInit() } for !timer.destoryHandleList.Empty() { handle := timer.destoryHandleList.FirstEntry().(XTimerDestoryHandleNode) handle.entry.DelInit() handle.cb() } if isDestory { timer.cb(TIMER_DESTORY_EVENT, nil) } else { timer.cb(TIMER_DELETE_EVENT, nil) } timer.cb = nil if timer.wp != nil { timer.wp.timer = nil timer.wp = nil } if toFreeList { this.addToFreeList(timer) } } func (this *XTimer) internalModifyTime(timer *XTimerList, expireTime int32) { this.detachTimer(timer) timer.expireTime = expireTime timer.expires = this.getTickCount(this.context) + int64(expireTime) this.internalAddTimer(timer) } func (this *XTimer) clearAttacher(attacher *XTimerAttacher) { var workList ListHead attacher.timers.ReplaceInit(&workList) for !workList.Empty() { timer := workList.FirstEntry().(*XTimerList) this.internalDelete(timer, false, true) } } func (this *XTimer) DeleteRunningTimer() { if this.runningTimer != nil { this.internalDelete(this.runningTimer, false, true) this.runningTimer = nil } }