268 lines
6.3 KiB
Lua
268 lines
6.3 KiB
Lua
local minHeapClass = require_ex("Common/Utils/DataStructure/MinHeap")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TimerManager = HL.Class('TimerManager')
|
|
|
|
|
|
TimerManager.m_heap = HL.Field(HL.Forward("MinHeap"))
|
|
|
|
|
|
TimerManager.m_unscaledHeap = HL.Field(HL.Forward("MinHeap"))
|
|
|
|
|
|
TimerManager.m_frameHeap = HL.Field(HL.Forward("MinHeap"))
|
|
|
|
|
|
TimerManager.m_removedTimerKeys = HL.Field(HL.Table)
|
|
|
|
|
|
TimerManager.m_groupTimerKeys = HL.Field(HL.Table)
|
|
|
|
|
|
TimerManager.m_nextTimerKey = HL.Field(HL.Number) << 1
|
|
|
|
|
|
TimerManager.m_frameCount = HL.Field(HL.Number) << 0
|
|
|
|
|
|
TimerManager.m_requestCache = HL.Field(HL.Forward("Stack"))
|
|
|
|
|
|
TimerManager.m_timerStackTraces = HL.Field(HL.Table)
|
|
|
|
|
|
|
|
|
|
TimerManager.TimerManager = HL.Constructor() << function(self)
|
|
self.m_heap = minHeapClass()
|
|
self.m_unscaledHeap = minHeapClass()
|
|
self.m_frameHeap = minHeapClass()
|
|
self.m_requestCache = require_ex("Common/Utils/DataStructure/Stack")()
|
|
self.m_removedTimerKeys = {}
|
|
self.m_groupTimerKeys = setmetatable({}, { __mode = "k" })
|
|
self.m_timerStackTraces = {}
|
|
self.m_nextTimerKey = 1
|
|
self.m_frameCount = 0
|
|
LuaUpdate:Add("Tick", function(deltaTime)
|
|
self:Tick(deltaTime)
|
|
end)
|
|
end
|
|
|
|
|
|
|
|
|
|
TimerManager.Tick = HL.Method(HL.Number) << function(self, deltaTime)
|
|
self.m_frameCount = self.m_frameCount + 1
|
|
self:_UpdateTimers(self.m_heap, Time.time)
|
|
self:_UpdateTimers(self.m_unscaledHeap, Time.unscaledTime)
|
|
self:_UpdateTimers(self.m_frameHeap, self.m_frameCount)
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
TimerManager._UpdateTimers = HL.Method(HL.Forward("MinHeap"), HL.Number) << function(self, heap, time)
|
|
while heap:Size() > 0 do
|
|
local request, triggerTime = heap:Min()
|
|
if self.m_removedTimerKeys[request.key] then
|
|
self.m_removedTimerKeys[request.key] = nil
|
|
heap:Pop()
|
|
if ENABLE_PROFILER then
|
|
self.m_timerStackTraces[request.key] = nil
|
|
end
|
|
self:_CacheRequest(request)
|
|
else
|
|
if time >= triggerTime then
|
|
heap:Pop()
|
|
if ENABLE_PROFILER then
|
|
local label = self.m_timerStackTraces[request.key]
|
|
if label and unity_sample and unity_sample.begin_unity_sample then
|
|
unity_sample.begin_unity_sample(label)
|
|
end
|
|
end
|
|
local succ, log = xpcall(request.action, debug.traceback)
|
|
if not succ then
|
|
logger.critical("Timer Action Fail\n", log)
|
|
end
|
|
if ENABLE_PROFILER then
|
|
if unity_sample and unity_sample.end_unity_sample then
|
|
unity_sample.end_unity_sample()
|
|
end
|
|
self.m_timerStackTraces[request.key] = nil
|
|
end
|
|
self:_CacheRequest(request)
|
|
else
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TimerManager.StartFrameTimer = HL.Method(HL.Number, HL.Function, HL.Opt(HL.Any)).Return(HL.Number)
|
|
<< function(self, frameNum, action, groupKey)
|
|
local triggerTime = self.m_frameCount + frameNum
|
|
local heap = self.m_frameHeap
|
|
return self:_StartTimer(heap, triggerTime, action, groupKey)
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TimerManager.StartTimer = HL.Method(HL.Number, HL.Function, HL.Opt(HL.Boolean, HL.Any)).Return(HL.Number)
|
|
<< function(self, time, action, unscaled, groupKey)
|
|
local triggerTime = (unscaled and Time.unscaledTime or Time.time) + time
|
|
local heap = unscaled and self.m_unscaledHeap or self.m_heap
|
|
return self:_StartTimer(heap, triggerTime, action, groupKey)
|
|
end
|
|
|
|
|
|
|
|
|
|
TimerManager.GetTimerTriggerTime = HL.Method(HL.Number).Return(HL.Number) << function(self, timerId)
|
|
for key, _ in self.m_heap:NodeIter() do
|
|
local request = key.key
|
|
if request.key == timerId then
|
|
return request.triggerTime
|
|
end
|
|
end
|
|
|
|
for key, _ in self.m_unscaledHeap:NodeIter() do
|
|
local request = key.key
|
|
if request.key == timerId then
|
|
return request.triggerTime
|
|
end
|
|
end
|
|
|
|
return -1
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TimerManager._StartTimer = HL.Method(HL.Forward("MinHeap"), HL.Number, HL.Function, HL.Opt(HL.Any)).Return(HL.Number)
|
|
<< function(self, heap, triggerTime, action, groupKey)
|
|
local key = self.m_nextTimerKey
|
|
self.m_nextTimerKey = self.m_nextTimerKey + 1
|
|
local request = self:_GetRequest()
|
|
request.key = key
|
|
request.action = action
|
|
request.triggerTime = triggerTime
|
|
request.groupKey = groupKey
|
|
|
|
if ENABLE_PROFILER then
|
|
self.m_timerStackTraces[key] = self:_GetCallerStackLabel()
|
|
end
|
|
|
|
heap:Add(request, triggerTime)
|
|
|
|
if groupKey ~= nil then
|
|
local keys = self.m_groupTimerKeys[groupKey]
|
|
if not keys then
|
|
keys = {}
|
|
self.m_groupTimerKeys[groupKey] = keys
|
|
end
|
|
table.insert(keys, key)
|
|
end
|
|
|
|
return key
|
|
end
|
|
|
|
|
|
|
|
|
|
TimerManager.ClearTimer = HL.Method(HL.Number) << function(self, key)
|
|
if key then
|
|
self.m_removedTimerKeys[key] = true
|
|
if ENABLE_PROFILER then
|
|
self.m_timerStackTraces[key] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
TimerManager.ClearAllTimer = HL.Method(HL.Any) << function(self, groupKey)
|
|
local keys = self.m_groupTimerKeys[groupKey]
|
|
if keys then
|
|
for _, k in pairs(keys) do
|
|
self:ClearTimer(k)
|
|
end
|
|
self.m_groupTimerKeys[groupKey] = nil
|
|
end
|
|
end
|
|
|
|
|
|
|
|
TimerManager._GetRequest = HL.Method().Return(HL.Table) << function(self)
|
|
if self.m_requestCache:Empty() then
|
|
return {}
|
|
else
|
|
return self.m_requestCache:Pop()
|
|
end
|
|
end
|
|
|
|
|
|
|
|
|
|
TimerManager._CacheRequest = HL.Method(HL.Table) << function(self, request)
|
|
request.action = nil
|
|
request.groupKey = nil
|
|
self.m_requestCache:Push(request)
|
|
end
|
|
|
|
|
|
|
|
TimerManager._GetCallerStackLabel = HL.Method().Return(HL.String) << function(self)
|
|
local thisSource
|
|
|
|
for level = 4, 12 do
|
|
local info = debug.getinfo(level, "Sl")
|
|
if info and info.what ~= "C" and info.source then
|
|
local src = info.source
|
|
if thisSource == nil or src ~= thisSource then
|
|
local line = info.currentline or 0
|
|
if src:sub(1,1) == "@" then src = src:sub(2) end
|
|
local last = src:match("[^/\\]+$") or src
|
|
return string.format("Timer:%s:%d", last, line)
|
|
end
|
|
end
|
|
end
|
|
return "Timer:Unknown"
|
|
end
|
|
|
|
HL.Commit(TimerManager)
|
|
return TimerManager |