- Joined
- Mar 29, 2016
- Messages
- 688
I based this work from the idea I found here which uses one universal timer for all 0.03125 period codes. Basically, what mine does is somewhat similar to the previous one but the difference is that it allows you to specify other periods aside from 0.03125 while still using a single timer for all registered codes.
However, this system works best for codes with periods divisible by 0.03125. Although any values greater than 0.03125 will work, it will cause the code execution interval not to be even. What does that mean? For example
So after 1 tick of the timer, the code's time becomes 0.03125 and won't run yet. Next, code's time will be 0.0625 and then it runs, leaving a remainder time of (0.0625 - 0.05) = 0.0125. So that remainder time will be added to the next tick and it will cause the code for example, to run two consecutive ticks then skips one tick then run another two consecutive ticks and so on. BUT this may not be much of a problem for codes with low frequency period such as those with timeouts greater than 2 seconds.
Please give your feedbacks on what to improve on or just feel free to comment =)
SCRIPT:
However, this system works best for codes with periods divisible by 0.03125. Although any values greater than 0.03125 will work, it will cause the code execution interval not to be even. What does that mean? For example
call RegisterLoopEvent(function Test, 0.05)
So after 1 tick of the timer, the code's time becomes 0.03125 and won't run yet. Next, code's time will be 0.0625 and then it runs, leaving a remainder time of (0.0625 - 0.05) = 0.0125. So that remainder time will be added to the next tick and it will cause the code for example, to run two consecutive ticks then skips one tick then run another two consecutive ticks and so on. BUT this may not be much of a problem for codes with low frequency period such as those with timeouts greater than 2 seconds.
Please give your feedbacks on what to improve on or just feel free to comment =)
SCRIPT:
JASS:
library LoopEvent uses Table
//! novjass
|=====|
| API |
|=====|
function RegisterLoopEvent takes code c, real timeout returns boolean/*
- Registers a code to run every <timeout> seconds and returns a boolean value depending
on the success of the operation
*/function RemoveLoopEvent takes code c returns boolean/*
- Unregisters a code from the loop and returns a boolean value depending
on the success of the operation
*///! endnovjass
//======================================================================================
globals
private constant real TIMEOUT = 0.03125
endglobals
//======================================================================================
globals
private Table hash
private timer Timer = CreateTimer()
private trigger array trig
private integer count = 0
private real array codeTimeout
private real array elapsed
endglobals
static if DEBUG_MODE then
private function Debug takes string msg returns nothing
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "|CFFFFCC00[LoopEvent] :|R" + msg)
endfunction
endif
private function RunLoop takes nothing returns nothing
local integer i = 0
loop
set i = i + 1
set elapsed[i] = elapsed[i] + TIMEOUT
if elapsed[i] >= codeTimeout[i] then
call TriggerEvaluate(trig[i])
set elapsed[i] = elapsed[i] - codeTimeout[i]
endif
exitwhen i == count
endloop
endfunction
function RegisterLoopEvent takes code c, real timeout returns boolean
local integer i = GetHandleId(Filter(c))
if timeout < TIMEOUT then
debug call Debug("ERROR: Entered code execution timeout is less than the minimum value (" + R2S(TIMEOUT) + ")")
elseif trig[hash.integer[i]] == null then
debug if timeout - (timeout/TIMEOUT)*TIMEOUT > 0.00 then
debug call Debug("WARNING: Entered code timeout is not divisible by " + R2S(TIMEOUT) + ", this code's execution interval will not be even")
debug endif
set count = count + 1
set elapsed[count] = 0.00
set codeTimeout[count] = timeout
set trig[count] = CreateTrigger()
call TriggerAddCondition(trig[count], Filter(c))
set hash.integer[i] = count
if count == 1 then
call TimerStart(Timer, TIMEOUT, true, function RunLoop)
debug call Debug("There is one code instance registered, starting to run timer")
endif
return true
debug else
debug call Debug("ERROR: Attempt to double register a code")
endif
return false
endfunction
function RemoveLoopEvent takes code c returns boolean
local integer i = hash.integer[GetHandleId(Filter(c))]
if trig[i] != null then
debug call Debug("Removing a code from the loop")
call TriggerClearConditions(trig[i])
call DestroyTrigger(trig[i])
set count = count - 1
if count == 0 then
call TimerStart(Timer, 0, false, null)
debug call Debug("There are no code instances running, stopping timer")
else
loop
set i = i + 1
exitwhen i > count + 1
set trig[i - 1] = trig[i]
set codeTimeout[i - 1] = codeTimeout[i]
endloop
endif
return true
endif
debug call Debug("ERROR: Attempt to remove a null or an already removed code")
return false
endfunction
private module M
static method onInit takes nothing returns nothing
set hash = Table.create()
endmethod
endmodule
private struct S extends array
implement M
endstruct
endlibrary