- Joined
- Dec 12, 2008
- Messages
- 7,385
Update:
Added Jass version.
Added Jass version.
local timer t=NewTimer()
call SetTimerData(t,this)
call TimerStart(t,T32_PERIOD,true,function thistype.callback)
set t=null
call TimerStart(NewTimerEx(this),T32_PERIOD,true,function thistype.callback)
call ReleaseTimer(t)
I also think that the QUANTITY should be applied no matter what. Similar to what I did with the projectile recycling system you should set a limit to the maximum amount of timers that can be stored, that way a sudden spike in the game will not cause that number to overflow into undesirable quantities. 256 timers is a fine enough number to use as a recyce cap but of course it'd be configurable.
library TimerUtils requires TimerUtilsEx
endlibrary
local integer d = GetTimerData(t)
//Run debug deallocate code
return d
I just learned about the importance of readable code![]()
I can't believe my ears. Maybe you're not as hopeless as you look like.
library TimerUtilsEx requires optional Table
/*************************************************
*
* TimerUtilsEx
* v2.1.0.0
* By Magtheridon96
*
* Original version by Vexorian.
*
* Flavors:
* Hashtable:
* - RAM: Minimal
* - Get/SetTimerData: Slow
*
* Array:
* - RAM: Maximal
* - Get/SetTimerData: Fast
*
* All the functions have O(1) complexity.
* The Array version is the fastest, but the hashtable
* version is the safest. The Array version is still
* quite safe though, and I would recommend using it.
* The system is much slower in debug mode.
*
* Optional Requirement:
* - Table by Bribe
* hiveworkshop.com/forums/showthread.php?t=188084
*
* API:
* ----
* - function NewTimer takes nothing returns timer
* - Returns a new timer from the stack.
* - function NewTimerEx takes integer i returns timer
* - Returns a new timer from the stack and attaches a value to it.
* - function ReleaseTimer takes timer t returns integer
* - Throws a timer back into the stack. Also returns timer data.
* - function SetTimerData takes timer t, integer value returns nothing
* - Attaches a value to a timer.
* - function GetTimerData takes timer t returns integer
* - Returns the attached value.
*
* Special Thanks To:
* - Bribe
* - Vexorian
* - Troll-Brain
*
*/
globals //Configuration
private constant boolean USE_HASH = false
private constant integer QUANTITY = 256 //The max number of timers that can be stored.
endglobals
globals
private timer array tT
private integer tN = 0
endglobals
//=======================================================================
// Module to initialize the system.
//
private module Init
private static method onInit takes nothing returns nothing
static if not USE_HASH then
local integer i = QUANTITY
loop
set i = i - 1
set tT[i] = CreateTimer()
exitwhen i == 0
endloop
set tN = QUANTITY
elseif LIBRARY_Table then
set .tb = Table.create()
endif
endmethod
endmodule
//=======================================================================
// A struct is needed to static-if out unwanted globals and to initialize
// the system in the highest priority (by implementing the module).
//
private struct Data extends array
static if not USE_HASH then
static integer array data
endif
static if LIBRARY_Table then
static Table tb = 0
else
static hashtable ht = InitHashtable()
endif
implement Init
endstruct
//=======================================================================
// "Is Timer Valid" function for debugging and double-free safety.
//
private function ITV takes integer i returns boolean
static if LIBRARY_Table then
return Data.tb.boolean[-i]
else
return LoadBoolean(Data.ht, i, 1)
endif
endfunction
//=======================================================================
// "Get Timer Data" function because the system already has the handle ID
// when it calls it. It inlines when not compiled in debug mode.
//
private function GTD takes integer id returns integer
debug if not ITV(id) then
debug call BJDebugMsg("[TimerUtils]Error: Tried to get data from invalid timer.")
debug endif
static if USE_HASH then
static if LIBRARY_Table then
return Data.tb[id]
else
return LoadInteger(Data.ht, id, 0)
endif
else
return Data.data[id - 0x100000]
endif
endfunction
//=======================================================================
// "Set Timer Data" function because the system already has the handle ID
// when it calls it. It inlines when not compiled in debug mode.
//
private function STD takes integer id, integer data returns nothing
debug if not ITV(id) then
debug call BJDebugMsg("[TimerUtils]Error: Tried to attach data to invalid timer.")
debug endif
static if USE_HASH then
static if LIBRARY_Table then
set Data.tb[id] = data
else
call SaveInteger(Data.ht, id, 0, data)
endif
else
set Data.data[id - 0x100000] = data
endif
endfunction
//=======================================================================
// Assign an integer to the timer. It inlines when not compiled in debug
// mode.
//
function SetTimerData takes timer t, integer data returns nothing
call STD(GetHandleId(t), data)
endfunction
//=======================================================================
// Get the integer from the timer. It inlines when not compiled in debug
// mode.
//
function GetTimerData takes timer t returns integer
return GTD(GetHandleId(t))
endfunction
//=======================================================================
// Returns a new timer with the specified integer attached to it.
//
function NewTimerEx takes integer data returns timer
local integer id
if tN == 0 then
static if USE_HASH then
set tT[0] = CreateTimer()
else
debug call BJDebugMsg("[TimerUtils]Error: No Timers In The Stack! You must increase 'QUANTITY'")
return null
endif
else
set tN = tN - 1
endif
set id = GetHandleId(tT[tN])
static if LIBRARY_Table then
set Data.tb.boolean[-id] = true
else
call SaveBoolean(Data.ht, id, 1, true)
endif
call STD(id, data)
return tT[tN]
endfunction
//=======================================================================
// Returns a new timer.
//
function NewTimer takes nothing returns timer
return NewTimerEx(0)
endfunction
//=======================================================================
// Release the timer when you're finished with it.
//
function ReleaseTimer takes timer t returns integer
local integer id = GetHandleId(t)
local integer data = 0
//Pause the timer just in case.
call PauseTimer(t)
//Make sure the timer is valid.
if ITV(id) then
//Get the timer's data.
set data = GTD(id)
//Unmark handle id as a valid timer.
static if LIBRARY_Table then
call Data.tb.boolean.remove(-id)
else
call RemoveSavedBoolean(Data.ht, id, 1)
endif
//If it's not run in USE_HASH mode, this next block is useless.
static if USE_HASH then
//At least clear hash memory while it's in the recycle stack.
static if LIBRARY_Table then
call Data.tb.remove(id)
else
call RemoveSavedInteger(Data.ht, id, 0)
endif
//Enforce the timer recycle limit.
if tN == QUANTITY then
call DestroyTimer(t)
return data
endif
endif
//Recycle the timer.
set tT[tN] = t
set tN = tN + 1
//Tried to pass a bad timer.
debug else
debug call BJDebugMsg("[TimerUtils]Error: Tried to release non-active timer!")
endif
//Return the timer data. This is perfect for one-shot timers.
return data
endfunction
endlibrary
library TimerUtils requires TimerUtilsEx
endlibrary
et Data.data[GetHandleId(t) - Data.baseIndex] = value
return Data.data[GetHandleId(t) - Data.baseIndex]
Magtheridon96, you need to update this. It doesn't even compile.
You can't say "soon", it's copyrighted by Blizzard.
The new NewTimerEx and ReleaseTimer functions are useful for sure, I'm glad you liked my idea.
Sorry Bribe, it wasn't on purpose ;PSpinnaker, that's why I posted the update (see the post above yours)
sure, why not.
edit
Honestly Bribe, I can't take credit for your hard work.
You should graveyard this thread and post this system as yours
I'm neither the one who wrote it originally, nor the one who fixed it![]()
I'll need a benchmark on that.I have even been able to get Nestharus to change his mind sometimes.
function Second takes nothing returns nothing
local timer t = GetExpiredTimer()
local Table data = GetTimerData(t)
call ReleaseTimer(t)
set t = null
//do stuff with data
call data.destroy()
endfunction
function First takes nothing returns nothing
local Table data = Table.create()
local timer t = NewTimer()
call SetTimerData(t, data)
call TimerStart(t, 1, false, function fn)
set t = null
//assign stuff to data
endfunction
function Second takes nothing returns nothing
local Table data = ReleaseTimer(GetExpiredTimer())
//do stuff with data
call data.destroy()
endfunction
function First takes nothing returns nothing
local Table data = Table.create()
call TimerStart(NewTimerEx(data), 1, false, function fn)
//assign stuff to data
endfunction
function Second takes nothing returns nothing
local Table data = Timeout.getData()
//do stuff with data
endfunction
function First takes nothing returns nothing
local Table data = Timeout.start(1, false, function fn)
//assign stuff to data
endfunction