initial commit
This commit is contained in:
8
External/AccurateTime/!AccurateTime.toc
vendored
Normal file
8
External/AccurateTime/!AccurateTime.toc
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
## Interface: 50400
|
||||
## Title: AccurateTime
|
||||
## Notes: Provides accurate, millisecond-level timing.
|
||||
## Author: Sapu94
|
||||
## Version: @project-version@
|
||||
|
||||
|
||||
AccurateTime.lua
|
||||
142
External/AccurateTime/AccurateTime.lua
vendored
Normal file
142
External/AccurateTime/AccurateTime.lua
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
--[[
|
||||
|
||||
This library is intended to fix the shortfalls of using debugprofilestop() for
|
||||
getting accurate sub-second timing in addons. Specifically, this library aims
|
||||
to prevent any conflicts that may arrise with multiple addons using
|
||||
debugprofilestart and debugprofilestop. While perfect accuracy is not
|
||||
guarenteed due to the potential for an addon to load before this library and
|
||||
use the original debugprofilestart/debugprofilestop functions, this library
|
||||
provides a best-effort means of correcting any issues if this is the case.
|
||||
The best solution is for addons to NOT use debugprofilestart() and to NOT store
|
||||
a local reference to debugprofilestop(), even if they aren't using this library
|
||||
directly.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
AccurateTime is hereby placed in the Public Domain
|
||||
See the wowace page for usage and documentation.
|
||||
Author: Sapu94 (sapu94@gmail.com)
|
||||
Website: http://www.wowace.com/addons/accuratetime/
|
||||
--]]
|
||||
|
||||
local _G = _G
|
||||
local AT_VERSION = 7
|
||||
|
||||
|
||||
-- Check if we're already loaded
|
||||
-- If this is a newer version, remove the old hooks and we'll re-hook
|
||||
if _G.AccurateTime then
|
||||
if _G.AccurateTime.version > AT_VERSION then
|
||||
-- newer (or same) version already loaded - abort
|
||||
return
|
||||
end
|
||||
|
||||
-- undo hook so we can re-hook
|
||||
debugprofilestart = _G.AccurateTime._debugprofilestart
|
||||
debugprofilestop = _G.AccurateTime._debugprofilestop
|
||||
end
|
||||
|
||||
|
||||
-- setup global library reference
|
||||
_G.AccurateTime = {}
|
||||
AccurateTime = _G.AccurateTime
|
||||
AccurateTime.version = AT_VERSION
|
||||
|
||||
-- Store original functions.
|
||||
-- debugprofilestart should never be called, but we'll store it just in case.
|
||||
AccurateTime._debugprofilestop = debugprofilestop
|
||||
AccurateTime._debugprofilestart = debugprofilestart
|
||||
AccurateTime._currentDebugprofilestop = debugprofilestop
|
||||
|
||||
-- other internal variables
|
||||
AccurateTime._errorTime = AccurateTime._errorTime or 0
|
||||
AccurateTime._timers = AccurateTime._timers or {}
|
||||
|
||||
|
||||
-- Gets the current time in milliseconds. Will be directly from the original
|
||||
-- debugprofilestop() with any error we've detected added in. This error would
|
||||
-- come solely from an addon calling the unhooked debugprofilestart().
|
||||
function AccurateTime:GetAbsTime()
|
||||
return AccurateTime._debugprofilestop() + AccurateTime._errorTime
|
||||
end
|
||||
|
||||
-- It is up to the caller to ensure the key they are using is unique.
|
||||
-- Using table reference or description strings is preferable.
|
||||
-- If no key is specified, a unique key will be created and returned.
|
||||
-- If the timer is already running, restart it.
|
||||
-- Usage: local key = AccurateTime:GetTimer([key])
|
||||
function AccurateTime:StartTimer(key)
|
||||
key = key or {}
|
||||
AccurateTime._timers[key] = AccurateTime._timers[key] or AccurateTime:GetAbsTime()
|
||||
return key
|
||||
end
|
||||
|
||||
-- gets the current value of a timer
|
||||
-- Usage: local value = AccurateTime:GetTimer(key[, silent])
|
||||
function AccurateTime:GetTimer(key, silent)
|
||||
assert(key, "No key specified.")
|
||||
if silent and not AccurateTime._timers[key] then return end
|
||||
assert(AccurateTime._timers[key], "No timer currently running for the given key.")
|
||||
return AccurateTime:GetAbsTime() - AccurateTime._timers[key]
|
||||
end
|
||||
|
||||
-- Removes a timer and returns its current value.
|
||||
-- Usage: local value = AccurateTime:StopTimer(key)
|
||||
function AccurateTime:StopTimer(key)
|
||||
local value = AccurateTime:GetTimer(key)
|
||||
AccurateTime._timers[key] = nil
|
||||
return value
|
||||
end
|
||||
|
||||
|
||||
-- apply hooks
|
||||
debugprofilestart = function() error("You should never use debugprofilestart()!", 2) end
|
||||
debugprofilestop = function() return AccurateTime._currentDebugprofilestop() end
|
||||
|
||||
|
||||
-- Create an OnUpdate script to detect and attempt to correct other addons
|
||||
-- which use the original (non-hooked) debugprofilestart(). This should in
|
||||
-- theory never happen, but we'll do a best-effort correction if it does.
|
||||
local function OnUpdate(self)
|
||||
local absTime = AccurateTime:GetAbsTime()
|
||||
if absTime < self.lastUpdateAbsTime then
|
||||
-- debugprofilestart() was called and the back-end timer was reset
|
||||
-- Estimate what the absolute time should be using GetTime() (converted
|
||||
-- to ms) and add it to AccurateTime._errorTime.
|
||||
local realAbsTime = self.lastUpdateAbsTime + (GetTime() - self.lastUpdateTime) * 1000
|
||||
AccurateTime._errorTime = AccurateTime._errorTime + (realAbsTime - absTime)
|
||||
if AccurateTime._errorTime > 0 then
|
||||
-- update AccurateTime._currentDebugprofilestop() to use our version of the function now that there is some error time
|
||||
AccurateTime._currentDebugprofilestop = function() return AccurateTime:GetAbsTime() end
|
||||
end
|
||||
end
|
||||
self.lastUpdateAbsTime = absTime
|
||||
self.lastUpdateTime = GetTime()
|
||||
end
|
||||
if not AccurateTime._frame then
|
||||
-- create frame just once
|
||||
AccurateTime._frame = CreateFrame("Frame")
|
||||
AccurateTime._frame.lastUpdateTime = GetTime()
|
||||
AccurateTime._frame.lastUpdateAbsTime = 0
|
||||
end
|
||||
-- upgrade the frame
|
||||
AccurateTime._frame:SetScript("OnUpdate", OnUpdate)
|
||||
|
||||
--[[
|
||||
function AccurateTimeTest()
|
||||
local start = debugprofilestop()
|
||||
for i=1, 10000000 do
|
||||
end
|
||||
print("loop", debugprofilestop()-start)
|
||||
start = debugprofilestop()
|
||||
for i=1, 10000000 do
|
||||
debugprofilestop()
|
||||
end
|
||||
print("overriden", debugprofilestop()-start)
|
||||
start = debugprofilestop()
|
||||
for i=1, 10000000 do
|
||||
AccurateTime._debugprofilestop()
|
||||
end
|
||||
print("raw", debugprofilestop()-start)
|
||||
end
|
||||
--]]
|
||||
Reference in New Issue
Block a user