![]() |
#1 | ||||||
Free Software Terrorist
Technical Director
|
![]() (Requires jasshelper 0.9.Z.something, better just get something like 0.A.2.6 or later)
__________________Timer recycling and attaching. -- It began as Anitarf complaining about CSSafety's name considering it really has not much to do with the caster system anymore. Ended up merging CSSafety and CSData, considerations:
The flavors:
![]() library TimerUtils initializer init //********************************************************************* //* TimerUtils (red+blue+orange flavors for 1.24b+) 2.0 //* ---------- //* //* To implement it , create a custom text trigger called TimerUtils //* and paste the contents of this script there. //* //* To copy from a map to another, copy the trigger holding this //* library to your map. //* //* (requires vJass) More scripts: htt://www.wc3c.net //* //* For your timer needs: //* * Attaching //* * Recycling (with double-free protection) //* //* set t=NewTimer() : Get a timer (alternative to CreateTimer) //* set t=NewTimerEx(x) : Get a timer (alternative to CreateTimer), call //* Initialize timer data as x, instead of 0. //* //* ReleaseTimer(t) : Relese a timer (alt to DestroyTimer) //* SetTimerData(t,2) : Attach value 2 to timer //* GetTimerData(t) : Get the timer's value. //* You can assume a timer's value is 0 //* after NewTimer. //* //* Multi-flavor: //* Set USE_HASH_TABLE to true if you don't want to complicate your life. //* //* If you like speed and giberish try learning about the other flavors. //* //******************************************************************** //================================================================ globals //How to tweak timer utils: // USE_HASH_TABLE = true (new blue) // * SAFEST // * SLOWEST (though hash tables are kind of fast) // // USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = true (orange) // * kinda safe (except there is a limit in the number of timers) // * ALMOST FAST // // USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = false (red) // * THE FASTEST (though is only faster than the previous method // after using the optimizer on the map) // * THE LEAST SAFE ( you may have to tweak OFSSET manually for it to // work) // private constant boolean USE_HASH_TABLE = true private constant boolean USE_FLEXIBLE_OFFSET = false private constant integer OFFSET = 0x100000 private integer VOFFSET = OFFSET //Timers to preload at map init: private constant integer QUANTITY = 256 //Changing this to something big will allow you to keep recycling // timers even when there are already AN INCREDIBLE AMOUNT of timers in // the stack. But it will make things far slower so that's probably a bad idea... private constant integer ARRAY_SIZE = 8190 endglobals //================================================================================================== globals private integer array data[ARRAY_SIZE] private hashtable ht endglobals //It is dependent on jasshelper's recent inlining optimization in order to perform correctly. function SetTimerData takes timer t, integer value returns nothing static if(USE_HASH_TABLE) then // new blue call SaveInteger(ht,0,GetHandleId(t), value) elseif (USE_FLEXIBLE_OFFSET) then // orange static if (DEBUG_MODE) then if(GetHandleId(t)-VOFFSET<0) then call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer") endif endif set data[GetHandleId(t)-VOFFSET]=value else // new red static if (DEBUG_MODE) then if(GetHandleId(t)-OFFSET<0) then call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer") endif endif set data[GetHandleId(t)-OFFSET]=value endif endfunction function GetTimerData takes timer t returns integer static if(USE_HASH_TABLE) then // new blue return LoadInteger(ht,0,GetHandleId(t) ) elseif (USE_FLEXIBLE_OFFSET) then // orange static if (DEBUG_MODE) then if(GetHandleId(t)-VOFFSET<0) then call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer") endif endif return data[GetHandleId(t)-VOFFSET] else // new red static if (DEBUG_MODE) then if(GetHandleId(t)-OFFSET<0) then call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer") endif endif return data[GetHandleId(t)-OFFSET] endif endfunction //========================================================================================== globals private timer array tT[ARRAY_SIZE] private integer tN = 0 private constant integer HELD=0x28829022 //use a totally random number here, the more improbable someone uses it, the better. private boolean didinit = false endglobals private keyword init //========================================================================================== // I needed to decide between duplicating code ignoring the "Once and only once" rule // and using the ugly textmacros. I guess textmacros won. // //! textmacro TIMERUTIS_PRIVATE_NewTimerCommon takes VALUE // On second thought, no. //! endtextmacro function NewTimerEx takes integer value returns timer if (tN==0) then if (not didinit) then //This extra if shouldn't represent a major performance drawback //because QUANTITY rule is not supposed to be broken every day. call init.evaluate() set tN = tN - 1 else //If this happens then the QUANTITY rule has already been broken, try to fix the // issue, else fail. debug call BJDebugMsg("NewTimer: Warning, Exceeding TimerUtils_QUANTITY, make sure all timers are getting recycled correctly") set tT[0]=CreateTimer() static if( not USE_HASH_TABLE) then debug call BJDebugMsg("In case of errors, please increase it accordingly, or set TimerUtils_USE_HASH_TABLE to true") static if( USE_FLEXIBLE_OFFSET) then if (GetHandleId(tT[0])-VOFFSET<0) or (GetHandleId(tT[0])-VOFFSET>=ARRAY_SIZE) then //all right, couldn't fix it call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.") return null endif else if (GetHandleId(tT[0])-OFFSET<0) or (GetHandleId(tT[0])-OFFSET>=ARRAY_SIZE) then //all right, couldn't fix it call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.") return null endif endif endif endif else set tN=tN-1 endif call SetTimerData(tT[tN],value) return tT[tN] endfunction function NewTimer takes nothing returns timer return NewTimerEx(0) endfunction //========================================================================================== function ReleaseTimer takes timer t returns nothing if(t==null) then debug call BJDebugMsg("Warning: attempt to release a null timer") return endif if (tN==ARRAY_SIZE) then debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!") //stack is full, the map already has much more troubles than the chance of bug call DestroyTimer(t) else call PauseTimer(t) if(GetTimerData(t)==HELD) then debug call BJDebugMsg("Warning: ReleaseTimer: Double free!") return endif call SetTimerData(t,HELD) set tT[tN]=t set tN=tN+1 endif endfunction private function init takes nothing returns nothing local integer i=0 local integer o=-1 local boolean oops = false if ( didinit ) then return else set didinit = true endif static if( USE_HASH_TABLE ) then set ht = InitHashtable() loop exitwhen(i==QUANTITY) set tT[i]=CreateTimer() call SetTimerData(tT[i], HELD) set i=i+1 endloop set tN = QUANTITY else loop set i=0 loop exitwhen (i==QUANTITY) set tT[i] = CreateTimer() if(i==0) then set VOFFSET = GetHandleId(tT[i]) static if(USE_FLEXIBLE_OFFSET) then set o=VOFFSET else set o=OFFSET endif endif if (GetHandleId(tT[i])-o>=ARRAY_SIZE) then exitwhen true endif if (GetHandleId(tT[i])-o>=0) then set i=i+1 endif endloop set tN = i exitwhen(tN == QUANTITY) set oops = true exitwhen not USE_FLEXIBLE_OFFSET debug call BJDebugMsg("TimerUtils_init: Failed a initialization attempt, will try again") endloop if(oops) then static if ( USE_FLEXIBLE_OFFSET) then debug call BJDebugMsg("The problem has been fixed.") //If this message doesn't appear then there is so much //handle id fragmentation that it was impossible to preload //so many timers and the thread crashed! Therefore this //debug message is useful. elseif(DEBUG_MODE) then call BJDebugMsg("There were problems and the new timer limit is "+I2S(i)) call BJDebugMsg("This is a rare ocurrence, if the timer limit is too low:") call BJDebugMsg("a) Change USE_FLEXIBLE_OFFSET to true (reduces performance a little)") call BJDebugMsg("b) or try changing OFFSET to "+I2S(VOFFSET) ) endif endif endif endfunction endlibrary ![]() Other TimerUtils Purple - Almost as fast as red but less safe to 'leaks' or using a lot of timers than blue. GroupUtils (needed by the CSSafety proxy http://www.wc3c.net/showthread.php?t=104464 . Last edited by Anitarf : 10-31-2011 at 05:18 PM. |
||||||
![]() |
![]() |
Sponsored Links - Login to hide this ad! |
|
![]() |
#2 | |
User
Join Date: Oct 2003
Posts: 150
![]() |
![]() Quote:
Glad the thing finally dropped "CS" from it as Anitarf was right it was definitely misleading. Last edited by Switch33 : 07-07-2008 at 12:14 AM. |
|
![]() |
![]() |
![]() |
#3 |
Corkscrew Chainsaw!!!
|
![]() You don't normally need groups for more than Enums, in which case you just use a global group and a tricky boolexpr. The only times you actually need a group are for say, saving all the units affected by a spell or something similar.
__________________ |
![]() |
![]() |
![]() |
#4 |
User
Join Date: Nov 2006
Posts: 304
![]() |
![]() Is this system better than TT? Meh, since i'm having issues with TT i'll give this a shot.
EDIT: What do you mean by lower values = fast but unsafe, should "safety" be of my concern? Last edited by Feroc1ty : 07-07-2008 at 03:49 AM. |
![]() |
![]() |
![]() |
#5 |
Panda > You
|
![]() I think all these timer systems are confusing the hell out of people
__________________ |
![]() |
![]() |
![]() |
#6 | ||||
Free Software Terrorist
Technical Director
|
![]() Quote:
Quote:
Why must everything be better? I am just trying to get something more consistent than CSSafety here. Quote:
Quote:
|
||||
![]() |
![]() |
![]() |
#7 | |
User
Join Date: Oct 2003
Posts: 150
![]() |
![]() Yea, that sounds better. So basically i would use something like 10 unit groups or so and recycle them(like re-empty them at the end of triggers and get a free one when i needed one).
Also it would be slower if u searched through all units with data on them in one single group than searching several groups i think. This is what i got so far... am i on the right track? ![]() library GroupRecycle globals unit group G[1] = CreateGroup() unit group G[2] = CreateGroup() unit group G[3] = CreateGroup() unit group G[4] = CreateGroup() unit group G[5] = CreateGroup() unit group G[6] = CreateGroup() unit group G[7] = CreateGroup() unit group G[8] = CreateGroup() unit group G[9] = CreateGroup() unit group G[10] = CreateGroup() endglobals function GetGroup takes nothing returns integer //this gives you a free group integer loop exitwhen i > 10 //Max # of groups if CountUnitsInGroup(G[i]) == 0 then return i //Returns first empty group it finds endif set i = i + 1 endloop return 11 //error if it ever gets this far endfunction function GroupRelease takes integer groupid returns nothing //this clears your free group integer call GroupClear(G[groupid]) endfunction endlibrary //Simple example of a trigger: function m takes nothing returns booleanexpr return true //standard filter function endfunction function forgroupfunc takes nothing returns nothing //do something with the units here endfunction function usegroup takes nothing returns nothing local integer i = GetGroup() local booleanxpr = Condition(m) set G[i] = GroupEnumUnitsInRange(G[i],x,y,radius, condition) call ForGroup(G[i],function forgroupfunc) //wait.. (spell ends) call GroupRelease(i) endfunction Quote:
QFT, yea... They all seem to all have "personal benefits" for each of them too if it wasn't enough to annoy the heck out of you trying to choose which ones to use. I think using like TT and HSAS works good. (Since i think HSAS is faster than ABC, but not faster than TT. Also TT only uses 1 timer. Another reason why is i don't like going back to gamecache really either.) Last edited by Switch33 : 07-07-2008 at 06:18 AM. |
|
![]() |
![]() |
![]() |
#8 |
master of fugue
Join Date: Jun 2007
Posts: 2,453
![]() ![]() ![]() ![]() ![]() |
![]() You probably want to remove this Vex: CS_H2I
__________________ |
![]() |
![]() |
![]() |
#9 |
Free Software Terrorist
Technical Director
|
![]() bleh, since CSData begins with a C it was getting added before TimerUtils in my sandbox so that syntax error wasn't catchable . lame.
__________________ |
![]() |
![]() |
![]() |
#10 | |
Panda > You
|
![]() Quote:
Im not making them, what I am saying is having something like 10 timer systems floating around just confusers new JASS programmers There should be just one general system that allows you to implement different methods with timers using macro's or something like |
|
![]() |
![]() |
![]() |
#11 | |
Free Software Terrorist
Technical Director
|
![]() Quote:
|
|
![]() |
![]() |
![]() |
#12 | |
Obscurity, the Art
|
![]() Quote:
|
|
![]() |
![]() |
![]() |
#13 | |
master of fugue
Join Date: Jun 2007
Posts: 2,453
![]() ![]() ![]() ![]() ![]() |
![]() Quote:
Any and all attaching to timers is bollocks. |
|
![]() |
![]() |
![]() |
#14 | |
Brahms-fan
Join Date: Jan 2006
Posts: 641
![]() ![]() ![]() ![]() |
![]() Why don't you just provide 1 global group for Enumerations and the like?
__________________Quote:
I disagree. If you want something to be perfectly timed (for matching an animation, for instance), it's much more comfortable attaching to a timer than using some kind of global loop or something. Last edited by Themerion : 07-07-2008 at 09:54 PM. |
|
![]() |
![]() |
![]() |
#15 |
Panda > You
|
![]() The problem with all these timer systems is that htey all have their own specific use in certain situations.
__________________One timer system is much more suited in one map/script then another, and thats why we have like 10 of these systems floating around To me it makes no difference, i make my own timer systems. If there was a very good tutorial fully explaining how attaching/hashing/pointers/handles works then I wouldn't be complaining but what inevitibly ends up happening is people end up using the completely wrong system |
![]() |
![]() |
![]() |
Thread Tools | Search this Thread |
|
|