Files
origin/sysmodule/frametimer/FrameGroup.go
2024-09-18 11:51:17 +08:00

203 lines
4.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package frametimer
import (
"container/heap"
"context"
"errors"
"github.com/duanhf2012/origin/v2/event"
"github.com/duanhf2012/origin/v2/log"
"time"
)
type TimerCB func(context.Context, FrameTimerID)
type _timerHeap struct {
timers []*timerData
}
func (h *_timerHeap) Len() int {
return len(h.timers)
}
func (h *_timerHeap) Less(i, j int) bool {
return h.timers[i].frameNum < h.timers[j].frameNum
}
func (h *_timerHeap) Swap(i, j int) {
h.timers[i], h.timers[j] = h.timers[j], h.timers[i]
h.timers[i].idx = i
h.timers[j].idx = j
}
func (h *_timerHeap) Push(x interface{}) {
td := x.(*timerData)
h.timers = append(h.timers, td)
td.idx = len(h.timers) - 1
}
func (h *_timerHeap) Pop() (ret interface{}) {
l := len(h.timers)
h.timers, ret = h.timers[:l-1], h.timers[l-1]
return
}
type FrameGroup struct {
groupID FrameGroupID
timerHeap _timerHeap
ft *FrameTimer
preTickGlobalFrameNum FrameNumber // 上次tick全局帧
preGlobalFrameNum FrameNumber // 上次设置的全局帧,用于更新FrameTimer.mapFrameGroup关系
frameNum FrameNumber // 当前帧
pause bool // 暂停状态
multiple uint8 // 位数默认1倍只允许1-5倍数
}
func (fg *FrameGroup) init() {
fg.timerHeap.timers = make([]*timerData, 0, 512)
fg.groupID = fg.ft.genGroupID()
fg.multiple = 1
heap.Init(&fg.timerHeap)
}
func (fg *FrameGroup) convertGlobalFrameNum(frameNum FrameNumber) FrameNumber {
return fg.ft.getGlobalFrameNumber() + (frameNum-fg.frameNum)/FrameNumber(fg.multiple)
}
func (fg *FrameGroup) refreshMinFrame() {
if fg.timerHeap.Len() == 0 || fg.pause {
return
}
globalFrameNum := fg.convertGlobalFrameNum(fg.timerHeap.timers[0].frameNum)
fg.ft.refreshGroupMinFrame(fg.groupID, fg.preGlobalFrameNum, globalFrameNum)
fg.preGlobalFrameNum = globalFrameNum
}
func (fg *FrameGroup) tick(globalFrame FrameNumber) {
fg.frameNum = fg.frameNum + (globalFrame-fg.preTickGlobalFrameNum)*FrameNumber(fg.multiple)
fg.preTickGlobalFrameNum = globalFrame
fg.onceTick()
fg.refreshMinFrame()
}
func (fg *FrameGroup) onceTick() {
for fg.timerHeap.Len() > 0 {
if fg.timerHeap.timers[0].frameNum > fg.frameNum {
break
}
t := heap.Pop(&fg.timerHeap).(*timerData)
ev := event.NewEvent()
ev.Type = event.Sys_Event_FrameTick
ev.Data = t
fg.ft.NotifyEvent(ev)
fg.ft.removeTimerData(t.timerID)
if t.tickerFrameNum != 0 {
fg.addTicker(t.timerID, t.tickerFrameNum, t.ctx, t.cb)
}
}
}
func (fg *FrameGroup) addTimer(timerID FrameTimerID, frame FrameNumber, ctx context.Context, cb TimerCB) {
nextFrame := fg.frameNum + frame
td := fg.ft.addTimerData(timerID, nextFrame, 0, ctx, cb)
heap.Push(&fg.timerHeap, td)
}
func (fg *FrameGroup) addTicker(timerID FrameTimerID, frame FrameNumber, ctx context.Context, cb TimerCB) {
nextFrame := fg.frameNum + frame
td := fg.ft.addTimerData(timerID, nextFrame, frame, ctx, cb)
heap.Push(&fg.timerHeap, td)
}
// SetMultiple 设置倍数允许倍数范围1-5
func (fg *FrameGroup) SetMultiple(multiple uint8) error {
if fg.multiple == multiple {
return nil
}
if multiple < 0 || multiple > maxMultiple {
return errors.New("invalid multiplier")
}
fg.multiple = multiple
fg.refreshMinFrame()
return nil
}
// FrameAfterFunc 创建After定时器
func (fg *FrameGroup) FrameAfterFunc(timerID *FrameTimerID, d time.Duration, ctx context.Context, cb TimerCB) {
fg.ft.locker.Lock()
defer fg.ft.locker.Unlock()
frame := FrameNumber(d / fg.ft.oneFrameTime)
newTimerID := fg.ft.genTimerID()
fg.addTimer(newTimerID, frame, ctx, cb)
*timerID = newTimerID
fg.refreshMinFrame()
}
// FrameNewTicker 创建Ticker定时器
func (fg *FrameGroup) FrameNewTicker(timerID *FrameTimerID, d time.Duration, ctx context.Context, cb TimerCB) {
fg.ft.locker.Lock()
defer fg.ft.locker.Unlock()
frame := FrameNumber(d / fg.ft.oneFrameTime)
newTimerID := fg.ft.genTimerID()
fg.addTicker(newTimerID, frame, ctx, cb)
*timerID = newTimerID
fg.refreshMinFrame()
}
// Pause 暂停定时器组
func (fg *FrameGroup) Pause() {
fg.ft.locker.Lock()
defer fg.ft.locker.Unlock()
fg.pause = true
fg.ft.removeGroup(fg.groupID, fg.preGlobalFrameNum)
fg.preGlobalFrameNum = 0
}
// Resume 唤醒定时器组
func (fg *FrameGroup) Resume() {
fg.ft.locker.Lock()
defer fg.ft.locker.Unlock()
fg.pause = false
fg.refreshMinFrame()
fg.preTickGlobalFrameNum = fg.ft.globalFrameNum
}
// CancelTimer 关闭定时器
func (fg *FrameGroup) CancelTimer(timerID FrameTimerID) {
fg.ft.locker.Lock()
defer fg.ft.locker.Unlock()
td := fg.ft.getTimerData(timerID)
if td == nil {
log.Error("cannot find timer", log.Uint64("timerID", uint64(timerID)))
return
}
heap.Remove(&fg.timerHeap, td.idx)
fg.ft.removeGroup(fg.groupID, fg.preGlobalFrameNum)
fg.preGlobalFrameNum = 0
fg.refreshMinFrame()
}
func (fg *FrameGroup) Close(){
fg.ft.removeGroup(fg.groupID, fg.preGlobalFrameNum)
delete(fg.ft.mapGroup,fg.groupID)
}