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 ( DEADLINE_TIMER = 0 REPEAT_TIMER = iota FIXED_TIMER = iota ) type Timer struct { freeTimerNum int32 freeTimerList ListHead runningTimer *TimerList timerTick int64 getTickCount func (interface{}) int64 getFixedTimerExpires func (interface{}, bool, int32, int64) 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 *Timer) Init( getTickCount func (interface{}) int64, getFixedTimerExpires func (interface{}, bool, int32, int64) int64, context interface{}, gcTime int32, cacheTimerNum int32) { initListHeadFunc := func (data interface{}) { head := data.(*ListHead) head.Init() } initListHeadFunc(&this.freeTimerList) TraverseArray(&this.tv1, initListHeadFunc) TraverseArray(&this.tv2, initListHeadFunc) TraverseArray(&this.tv3, initListHeadFunc) TraverseArray(&this.tv4, initListHeadFunc) TraverseArray(&this.tv5, initListHeadFunc) this.timerTick = getTickCount(context) this.context = context this.getTickCount = getTickCount this.getFixedTimerExpires = getFixedTimerExpires this.cacheTimerNum = cacheTimerNum this.AddRepeatTimer( gcTime, func (params *XParams) { }, this.gcTimerFunc) } func (this *Timer) UnInit() { this.clear() } func (this *Timer) clear() { freeTimerFunc := func (data interface{}) { head := data.(*ListHead) for !head.Empty() { timerList := head.FirstEntry().(*TimerList) this.detachTimer(timerList) if !timerList.attachEntry.Empty() { timerList.attachEntry.DelInit() } } } freeTimerFunc(&this.freeTimerList) TraverseArray(&this.tv1, freeTimerFunc) TraverseArray(&this.tv2, freeTimerFunc) TraverseArray(&this.tv3, freeTimerFunc) TraverseArray(&this.tv4, freeTimerFunc) TraverseArray(&this.tv5, freeTimerFunc) } func (this *Timer) 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() { timerList := workList.FirstEntry().(*TimerList) this.runningTimer = timerList if timerList.timerFunc != nil { timerList.timerFunc(&timerList.params) } if timerList.timerAfterFunc != nil { timerList.timerAfterFunc(&timerList.params) } if this.runningTimer != nil { switch this.runningTimer.timerType { case REPEAT_TIMER, FIXED_TIMER: this.modifyTimerEx(timerList, timerList.milliSeconds, false) case DEADLINE_TIMER: this.detachTimer(timerList) this.addToFreeList(timerList) } } } } this.runningTimer = nil } func (this *Timer) NewTimerAttacher() *TimerAttacher { attacher := new(TimerAttacher) attacher.timer = this attacher.timers.Init() return attacher } func (this *Timer) AddDeadLineTimer( milli_seconds int32, init_func func (params* XParams), timer_func func (params* XParams)) *TimerList { return this.AddDeadLineTimerEx(milli_seconds, init_func, timer_func, nil) } func (this *Timer) AddDeadLineTimerEx( milli_seconds int32, init_func func (params* XParams), timer_func func (params* XParams), install_func func (timerList *TimerList, params* XParams)) *TimerList { timerList := this.newTimerList() timerList.params.Reset() if init_func != nil { init_func(&timerList.params) } timerList.initTimerList(this, DEADLINE_TIMER, milli_seconds, timer_func) if install_func != nil { install_func(timerList, &timerList.params) } this.ModifyTimer(timerList, milli_seconds) return timerList } func (this *Timer) AddRepeatTimer( milli_seconds int32, init_func func (params* XParams), timer_func func (params* XParams)) *TimerList { return this.AddRepeatTimerEx(milli_seconds, init_func, timer_func, nil) } func (this *Timer) AddRepeatTimerEx( milli_seconds int32, init_func func (params* XParams), timer_func func (params* XParams), install_func func (timer_list *TimerList, params* XParams)) *TimerList { timerList := this.newTimerList() if init_func != nil { init_func(&timerList.params) } timerList.initTimerList(this, REPEAT_TIMER, milli_seconds, timer_func) if install_func != nil { install_func(timerList, &timerList.params) } this.ModifyTimer(timerList, milli_seconds) return timerList } func (this *Timer) AddFixedTimer( milli_seconds int32, init_func func (params* XParams), timer_func func (params* XParams)) *TimerList { return this.AddFixedTimerEx(milli_seconds, init_func, timer_func, nil) } func (this *Timer) AddFixedTimerEx( milli_seconds int32, init_func func (params* XParams), timer_func func (params* XParams), install_func func (timer_list *TimerList, params* XParams)) *TimerList { timerList := this.newTimerList() if init_func != nil { init_func(&timerList.params) } timerList.initTimerList(this, FIXED_TIMER, milli_seconds, timer_func) if install_func != nil { install_func(timerList, &timerList.params) } this.ModifyTimer(timerList, milli_seconds) return timerList } func (this *Timer) ModifyTimer(timerList *TimerList, milliSeconds int32) { this.modifyTimerEx(timerList, milliSeconds, true) } func (this *Timer) modifyTimerEx(timerList *TimerList, milliSeconds int32, isFirstAdd bool) { this.detachTimer(timerList) timerList.milliSeconds = milliSeconds if timerList.timerType == FIXED_TIMER { tick := this.getTickCount(this.context) timerList.expires = this.getFixedTimerExpires( this.context, isFirstAdd, milliSeconds, tick) } else { timerList.expires = this.getTickCount(this.context) + int64(milliSeconds) } this.internalAddTimer(timerList) } func (this *Timer) DeleteTimer(timerList *TimerList) { if timerList == nil { return } if this.runningTimer == timerList { this.runningTimer = nil } if timerList.timerAfterFunc != nil { timerList.timerAfterFunc(&timerList.params) } this.detachTimer(timerList) this.addToFreeList(timerList) } func (this *Timer) GetRemainTime(timerList *TimerList) int64 { if timerList == nil { return 0 } remainTime := timerList.expires - this.getTickCount(this.context) if remainTime < 0 { return 0 } else { return remainTime } } func (this *Timer) GetRunningTimer() *TimerList { return this.runningTimer } func (this *Timer) 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 *Timer) detachTimer(timerList *TimerList) { if !timerList.entry.Empty() { timerList.entry.DelInit() } } func (this *Timer) addToFreeList(timerList *TimerList) { timerList.reset() this.freeTimerList.AddTail(&timerList.entry) this.freeTimerNum++ } func (this *Timer) 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.(*TimerList)) pos = next next = pos.next } } cascadeList.Init() return index } func (this *Timer) internalAddTimer(timerList *TimerList) { 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 *Timer) getTimerIndex(index uint32) uint32 { return (uint32)((this.timerTick >> (TVR_BITS + index * TVN_BITS)) & TVN_MASK); } func (this *Timer) newTimerList() *TimerList { if !this.freeTimerList.Empty() { timerList := this.freeTimerList.FirstEntry().(*TimerList) this.freeTimerNum-- return timerList } else { timerList := new(TimerList) timerList.init() return timerList } } func (this *Timer) gcTimerFunc(params *XParams) { count := 0 for ; !this.freeTimerList.Empty() && this.freeTimerNum > this.cacheTimerNum; { timerList := this.freeTimerList.FirstEntry().(*TimerList) timerList.entry.DelInit() this.freeTimerNum-- count++ if count > 1000 { break } } }