diff --git a/listhead.go b/listhead.go new file mode 100644 index 0000000..af5c8a6 --- /dev/null +++ b/listhead.go @@ -0,0 +1,50 @@ +package q5 + +type ListHead struct { + next *ListHead + prev *ListHead + data interface{} +} + +func (this *ListHead) Init() { + this.next = this + this.prev = this + this.data = nil +} + +func (this *ListHead) Del() { + this.next.prev = this.prev + this.prev.next = this.next + this.Init() +} + +func (this *ListHead) AddTail(pnew *ListHead) { + tmp_prev := this.prev + this.prev = pnew + pnew.next = this + pnew.prev = tmp_prev + tmp_prev.next = pnew +} + +func (this *ListHead) FirstEntry() interface{} { + return this.next.data +} + +func (this *ListHead) Replace(pnew *ListHead) { + pnew.next = this.next + pnew.next.prev = pnew + pnew.prev = this.prev + pnew.data = this.data +} + +func (this *ListHead) ReplaceInit(pnew *ListHead) { + this.Replace(pnew) + this.Init() +} + +func (this *ListHead) Empty() bool { + return this.next == this +} + +func (this *ListHead) DelInit() { +} diff --git a/timer.go b/timer.go new file mode 100644 index 0000000..624f95a --- /dev/null +++ b/timer.go @@ -0,0 +1,171 @@ +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 + freeTimer ListHead + runningTimer *TimerList + timerTick int64 + getTickCount func () int64 + content interface{} + gcTime int32 + cacheTimerNum int32 + tv1 [TVR_SIZE]ListHead + tv2 [TVN_SIZE]ListHead + tv3 [TVN_SIZE]ListHead + tv4 [TVN_SIZE]ListHead + tv5 [TVN_SIZE]ListHead + workList ListHead + cascadeList ListHead +} + +func (this *Timer) Init( + getTickCount func () int64, + content interface{}, + gcTime int32, + cacheTimerNum int32) { + this.getTickCount = getTickCount + this.content = content + this.gcTime = gcTime + this.cacheTimerNum = cacheTimerNum +} + +func (this *Timer) UnInit() { + this.clear() +} + +func (this *Timer) clear() { + +} + +func (this *Timer) Update() { + for this.getTickCount() >= this.timerTick { + index := uint32(this.timerTick & TVR_MASK) + + if index == 0 && + this.cascade(&this.tv2, this.getTimerIndex(index)) == 0 && + this.cascade(&this.tv3, this.getTimerIndex(index)) == 0 && + this.cascade(&this.tv4, this.getTimerIndex(index)) == 0 { + this.cascade(&this.tv5, this.getTimerIndex(index)) + } + this.timerTick += 1 + this.tv1[index].ReplaceInit(&this.workList) + for !this.workList.Empty() { + timer_list := this.workList.FirstEntry().(*TimerList) + this.runningTimer = timer_list + if timer_list.timerFunc != nil { + timer_list.timerFunc(&timer_list.params) + } + if timer_list.timerAfterFunc != nil { + timer_list.timerAfterFunc(&timer_list.params) + } + if this.runningTimer != nil { + switch this.runningTimer.timerType { + case REPEAT_TIMER, FIXED_TIMER: + if timer_list.timerType == FIXED_TIMER { + timer_list.fixedTimierExecuteTimes += 1 + } + this.ModifyTimer(timer_list, timer_list.milliSeconds) + case DEADLINE_TIMER: + this.detachTimer(timer_list) + if timer_list.attachEntry.Empty() { + timer_list.attachEntry.DelInit() + } + this.addToFreeList(timer_list) + } + } + } + } + this.runningTimer = nil +} + +func (this *Timer) AddDeadLineTimer( + milli_seconds int32, + init_func func (params* XParams), + timer_func func (params* XParams)) ITimerList { + 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 (timer_list ITimerList, params* XParams)) ITimerList { + if init_func != nil { + init_func(new(XParams)) + } + return nil +} + +func (this *Timer) ModifyTimer(timerList *TimerList, milli_seconds int32) { + +} + +func (this *Timer) detachTimer(timerList *TimerList) { + +} + +func (this *Timer) addToFreeList(timerList *TimerList) { + +} + +func (this *Timer) cascade(tv *[TVN_SIZE]ListHead, index uint32) uint32 { + tv[index].ReplaceInit(&this.cascadeList) + + if !this.cascadeList.Empty() { + pos := this.cascadeList.next + next := pos.next + for pos != &this.cascadeList { + this.internalAddTimer(pos.data.(*TimerList)) + pos = next + next = pos.next + } + } + this.cascadeList.Init() + return index +} + +func (this *Timer) internalAddTimer(timer_list *TimerList) { + expires := timer_list.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_MASK) + vec = &this.tv2[index] + } else if idx < (1 << (TVR_BITS + 2 * TVN_BITS)) { + index = (uint32)(expires & TVR_MASK) + vec = &this.tv3[index] + } else if idx < (1 << (TVR_BITS + 3 * TVN_BITS)) { + index = (uint32)(expires & TVR_MASK) + vec = &this.tv4[index] + } else { + index = (uint32)(expires & TVR_MASK) + vec = &this.tv5[index] + } + vec.AddTail(&timer_list.entry) +} + +func (this *Timer) getTimerIndex(index uint32) uint32 { + return (uint32)((this.timerTick >> (TVR_BITS + index * TVN_BITS)) & TVN_MASK); +} diff --git a/timerlist.go b/timerlist.go new file mode 100644 index 0000000..085d1ee --- /dev/null +++ b/timerlist.go @@ -0,0 +1,33 @@ +package q5 + +type ITimerList interface { + SetTimerAfterFunc(timer_after_func func(params *XParams)) +} + +type TimerList struct { + entry ListHead + attachEntry ListHead + timerType int8 + milliSeconds int32 + expires int64 + fixedTimierExecuteTimes int32 + + timerFunc func (params *XParams) + timerAfterFunc func (params *XParams) + params XParams +} + +func (this *TimerList) InitTimerList( + timer *Timer, + timerType int8, + millSeconds int32, + params XParams, + timerFunc func (params *XParams), + timerAfterFunc func (params *XParams)) { + this.timerType = timerType + this.milliSeconds = millSeconds + this.fixedTimierExecuteTimes = 0 + this.timerFunc = timerFunc + this.timerAfterFunc = timerAfterFunc + this.params = params +} diff --git a/types.go b/types.go new file mode 100644 index 0000000..10a210f --- /dev/null +++ b/types.go @@ -0,0 +1 @@ +package q5 diff --git a/xobject.go b/xobject.go new file mode 100644 index 0000000..1e595c0 --- /dev/null +++ b/xobject.go @@ -0,0 +1,16 @@ +package q5 + +const ( + XOT_SIMPLE = 0 + XOT_ARRAY = iota + XOT_OBJECT = iota +) + +type XObject struct { + _type int8 + _val interface{} +} + +func (this *XObject) AsXValue() *XValue { + return nil +} diff --git a/xparams.go b/xparams.go new file mode 100644 index 0000000..7136b68 --- /dev/null +++ b/xparams.go @@ -0,0 +1,12 @@ +package q5 + +type XParams struct { + Sender XValue + Param1 XValue + Param2 XValue + Param3 XValue +} + +func (this *XParams) SetInt32(val int32) *XParams { + return this +} diff --git a/xvalue.go b/xvalue.go new file mode 100644 index 0000000..ae24579 --- /dev/null +++ b/xvalue.go @@ -0,0 +1,85 @@ +package q5 + +import ( + "strconv" +) + +const ( + XVT_INT = 0 + XVT_FLOAT = iota + XVT_STRING = iota + XVT_BYTES = iota + XVT_USERDATA = iota +) + +type XValue struct +{ + _type int8 + _val interface{} +} + +func (this *XValue) GetType() int8 { + return this._type +} + +func (this *XValue) SetInt64(val int64) *XValue { + val_copy := val + this._type = XVT_INT + this._val = &val_copy + return this +} + +func (this *XValue) SetFloat64(val float64) *XValue { + val_copy := val + this._type = XVT_FLOAT + this._val = &val_copy + return this +} + +func (this *XValue) SetString(val string) *XValue { + val_copy := "" + val + this._type = XVT_STRING + this._val = &val_copy + return this +} + +func (this *XValue) SetBytes(val []byte) *XValue { + val_copy := val + this._type = XVT_FLOAT + this._val = &val_copy + return this +} + +func (this *XValue) SetUserData(val interface{}) *XValue { + val_copy := val + this._type = XVT_FLOAT + this._val = &val_copy + return this +} + +func (this *XValue) GetInt64() int64 { + switch this._type { + case XVT_INT: + return *(this._val.(*int64)) + case XVT_FLOAT: + return int64(*(this._val.(*float64))) + case XVT_STRING, XVT_BYTES, XVT_USERDATA: + val, err := strconv.ParseInt(this.GetString(), 10, 64) + if err == nil { + return val + } else { + val, err := strconv.ParseFloat(this.GetString(), 64) + if err == nil { + return int64(val) + } else { + return 0 + } + } + default: + return 0 + } +} + +func (this *XValue) GetString() string { + return "" +}