| 07-28-2007, 05:52 PM | #1 |
Hi everybody, I finished a system that alows us to use timers and associated data, without any use of gamecache. I just wanted some feedback, improvement ideas and even spelling corrections =p... And is is faster than gamecache ? JASS://*************************************************************************************************** //* Timer interface : //* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ //* This system links a timer to a struct, and automatically run the .end() method when //* the timer expires. //* //* Each struct that uses a timer must extend the s_timer interface. //* These structs must include 3 specific methods: //* - end method : defines actions executed when the timer ends //* - onDestroy method : releases the timer when the struct is destroyed. //* - create method : init the struct variables, and set up a timer if needed. //* //* Example : //* ¯¯¯¯¯¯¯¯¯ //* struct my_struct extends s_timer //* //my variables //* //* method end takes nothing returns nothing //* //my ending actions : remove a buff, kill a unit, etc... //* //you may have to call the .destroy() method, if the struct won't be used anymore and if you don't call it elsewhere. //* endmethod //* //* method onDestroy takes nothing returns nothing //* //my onDestroy actions (if you include structs in this struct by example) //* if( .ti!=null )then //* call ReleaseTimer(.ti) //* endif //* endmethod //* //* static method create takes <type> arg1, <type> arg2, boolean timed returns my_struct //* local my_struct s = my_struct.allocate() //* if( timed )then //* set s.ti = NewTimer() //* call SetTimerValue( s.ti, s ) //* endif //* //init. of my variables //* return s //* endmethod //* //* endstruct //* //* //* You may need to use only 2 functions, that are SetTimerValue and LaunchTimer, other functions //* are internal to the system. //* //*************************************************************************************************** scope timer globals private timer array T private timer array U private integer Tn = 0 private integer Un = 0 private s_timer array Uval endglobals interface s_timer timer ti = null method end takes nothing returns nothing endinterface private function FindListedTimer takes timer ti returns integer local integer i = 1 //search the timer in the list loop //returns 0 if timer is not exitwhen(U[i]==null) //found. if( U[i]==ti )then return i endif set i=i+1 endloop return 0 endfunction private function FlushActiveTimer takes timer ti returns nothing local integer i = FindListedTimer(ti) if( i!=0 )then //if the time is found, if( i!=Un )then //and if it isn't at the end of list set U[i] = U[Un] //then change the index of the last set Uval[i] = Uval[Un] //timer of the list, to the deleted endif //one. set U[Un] = null //Delete the last stored timer set Uval[Un] = 0 //and clear it's value. set Un = Un-1 endif endfunction private function EndTimer takes nothing returns nothing //Run when a timer expires local integer i = FindListedTimer( GetExpiredTimer() ) if( i!=0 )then //if the timer is found in the list, call Uval[i].end() //then call it's associated endif //.end() method. endfunction //** function SetTimerValue takes timer ti, s_timer value returns nothing local integer i = FindListedTimer(ti) if( i==0 )then //if the time is not found, set Un = Un+1 //increase list's items count set i = Un endif set U[i] = ti //store the timer in the list set Uval[i] = value //and it's associated struct endfunction function LaunchTimer takes timer ti, real dur returns nothing call PauseTimer(ti) //Pause the timer to prevent bugs call TimerStart( ti, dur, false, function EndTimer) //start the timer endfunction //*************************************************************************************************** //* Timers recycling functions : //* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ //* Based on CSSafety system (by Vexorian), improved by myself. //* //* This system recycles timers : //* //* When you need a timer just use the NewTimer() function, it will look in the stack for a free //* timer and return one if it is available, else it will create and return a new one. //* //* When you don't need your timer anymore, instead of use the DestroyTimer function, call the //* ReleaseTimer function, that will pause and store the timer in the stack, to be used again //* when needed. //* Then you'll no longer have to care about setting timers to null nor about timer related issues //* with the handle index stack. //* //*************************************************************************************************** function ReleaseTimer takes timer ti returns nothing if( ti!=null )then call PauseTimer(ti) call FlushActiveTimer(ti) if (Tn==8191) 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(ti) set ti = null else set T[Tn] = ti set Tn = Tn+1 endif endif endfunction function NewTimer takes nothing returns timer if( Tn==0 )then return CreateTimer() endif set Tn=Tn-1 return T[Tn] endfunction function NewTimerI takes nothing returns integer if( Tn==0 )then return h2I(CreateTimer()) endif set Tn=Tn-1 return h2I(T[Tn]) endfunction endscope EDIT : some usage examples Simple timer usage : JASS:function my_end_func takes nothing returns nothing call ReleaseTimer( GetExpiredTimer() ) endfunction function AA takes nothing returns nothing local timer ti = NewTimer() call StartTimer( ti, is_periodic, 5.00, func my_end_func ) endfunction or with an associated struct, using the fist example above : JASS:function BB takes <type> arg1, <type> arg2 returns nothing local my_struct S = my_struct.create( arg1, arg2, true ) call LaunchTimer( S.ti, 5.00 ) endfunction |
| 07-28-2007, 07:50 PM | #2 |
Hmm. It probably won't be too bad (as long as you're not abusing timers all over the place). I prefer something like Vex's timer substitute setup (heap for log n operations and operates off a single timer). You can find an example of his in his Hydra spell if I recall correctly. |
