q5/timer.go
aozhiwei 6fd253d455 1
2020-09-08 18:26:02 +08:00

344 lines
8.9 KiB
Go

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) {
for i := 0; !this.freeTimerList.Empty() && this.freeTimerNum > this.cacheTimerNum && i < 1000; i++ {
timerList := this.freeTimerList.FirstEntry().(*TimerList)
timerList.entry.DelInit()
this.freeTimerNum--
}
}