System vTimer

Azlier

Old World Ghost
Reaction score
461
It's like TimerUtils, but... slower. Doesn't use H2I.

Features:
JASS:
//Static methods
vTimer.start(callback, period)
//Starts a vTimer and returns it, so you can pause it and such.

//Methods
vTimer.pause()
//Pauses a vTimer.
vTimer.resume()
//Causes a paused vTimer to resume running.

//Use "return true" when you want to end execution of a function


Here's a test script, because actions are louder than birds, or something like that.
JASS:
scope Test initializer Init

private function Callback1 takes nothing returns boolean
    call BJDebugMsg("Callback1. Data: " + I2S(VT_GetTriggering().data))
    return true
endfunction

private function Callback2 takes nothing returns boolean
    call BJDebugMsg("Callback2. Data: " + I2S(VT_GetTriggering().data))
    return true
endfunction

private function Callback3 takes nothing returns boolean
    call BJDebugMsg("Callback3. Data: " + I2S(VT_GetTriggering().data))
    return true
endfunction

private function Callback4 takes nothing returns boolean
    call BJDebugMsg("Callback4. Data: " + I2S(VT_GetTriggering().data))
    return true
endfunction

private function Actions takes nothing returns nothing
    local vTimer v
    call ClearTextMessages()
    set v = vTimer.start(function Callback1, 0.5)
    set v.data = 3
    set v = vTimer.start(function Callback2, 0.25)
    set v.data = 1
    set v = vTimer.start(function Callback3, 1)
    set v.data = 7
    set v = vTimer.start(function Callback4, 0.75)
    set v.data = 3
endfunction

private function Init takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterPlayerEvent(t, Player(0), EVENT_PLAYER_END_CINEMATIC)
    call TriggerAddAction(t, function Actions)
endfunction

endscope


Only real advantage over something like KT is that you can pause the timer at any time.

Also vJassier than TimerUtils, but an alternate interface can certainly be programmed in. Major thanks to Jesus4Lyf who brought you the current version. I myself forged the idea.

Benchmark results (from Jesus, because I can't benchmark. I'm just gonna have to trust him.)
TU Red: 30100 execs/sec
TU Blue: 24700 execs/sec
VT: 22300 execs/sec

JASS:
library_once VT
    globals
        private integer MAX_TIMERS = 256
        //Preloading timers with this is much slower than with normal TimerUtils.
        //A maximum of about 600 is recommended. Besides, if you have more
        //then 600 timers running at once, you're doing it wrong.
    endglobals

    //** System Code **

    globals
        private boolexpr ReleaseCond
    endglobals
    
    private function SetTriggerData takes trigger t, integer d returns nothing
        if d>30 then
            call SetTriggerData.execute(t,d-30)
            set d=30
        endif
        loop
            exitwhen d==0
            set d=d-1
            call TriggerExecute(t)
        endloop
    endfunction
    
    public constant function GetTriggering takes nothing returns vTimer
        return GetTriggerExecCount(GetTriggeringTrigger())
    endfunction

    struct vTimer
        // Public:
        integer data
        
        private timer tim
        private trigger trig
        private boolexpr cond
        
        private static vTimer array Stack
        private static integer StackMax=0
        private method stack takes nothing returns nothing
            set .StackMax=.StackMax+1
            set .Stack[.StackMax]=this
        endmethod
        private static method create takes nothing returns vTimer
            local vTimer this=vTimer.allocate()
            set this.tim=CreateTimer()
            set this.trig=CreateTrigger()
            call SetTriggerData.execute(this.trig,this)
            call TriggerRegisterTimerExpireEvent(this.trig,this.tim)
            call this.stack()
            return this
        endmethod
        private static method new takes nothing returns vTimer
            debug if .StackMax==0 then
            debug    call BJDebugMsg("vTimer ERROR: Timer limit exceeded! Check for timer leaks. If there are none, increase the timer limit.")
            debug endif
            set .StackMax=.StackMax-1
            return .Stack[.StackMax+1]
        endmethod
        
        // Public:
        method pause takes nothing returns nothing
            call PauseTimer(this.tim)
        endmethod
        method resume takes nothing returns nothing
            call ResumeTimer(this.tim)
        endmethod
        
        // Public:
        static method start takes code callback, real period returns vTimer
            local vTimer this=vTimer.new()
            set this.cond=And(Condition(callback),ReleaseCond)
            call TriggerAddCondition(this.trig,this.cond)
            call TimerStart(this.tim,period,true,null)
            return this
        endmethod
        
        private method release takes nothing returns nothing
            call this.stack()
            call PauseTimer(this.tim)
            call TriggerClearConditions(this.trig)
            call DestroyBoolExpr(this.cond)
            set this.cond=null
        endmethod
        
        private static method releaseCond takes nothing returns boolean
            call GetTriggering().release()
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            set ReleaseCond = Condition(function vTimer.releaseCond)
            loop
                exitwhen MAX_TIMERS==0
                set MAX_TIMERS=MAX_TIMERS-1
                call vTimer.create()
            endloop
        endmethod
    endstruct
    
    public function Start takes code f, real period returns vTimer
        return vTimer.start(f,period)
    endfunction
endlibrary
 

Attachments

  • vTimer.w3x
    15.3 KB · Views: 249

Jesus4Lyf

Good Idea™
Reaction score
397
So um. It holds that one advantage over KT, but how about advantages over TU Blue?

Speed? Nup (well, maybe yes for a large number of handles).
Stability? Nup (well yes if you have over 400,000 handles or something, otherwise its about the same).
Interface? Yes, actually. This is much nicer in my opinion.

I'd still be inclined to use this system personally because it uses no H2I, but that's because I'm cracked. :D

Either way, nice sys in my opinion. And look! I even doubled its speed! Within ~25% of TU Red. :thup:

PS. You badly need some documentation. ;)
 

Azlier

Old World Ghost
Reaction score
461
Then I misread the benchmark. I thought it said it was faster. Let me fix that...
 

Azlier

Old World Ghost
Reaction score
461
I know, I know... and you are a fool. You privatized the release method! :p
 

Azlier

Old World Ghost
Reaction score
461
But that's disgusting. I like my release :(. It makes more sense.
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
Awesome? Yes. :D
Clever and interesting at least, however i would still used H2I, because it's far easier to code with, and the performance gain doesn't really matter, or i'm wrong ?

Actually, this has a nicer interface, too. :)
Nicer interface than TimerUtils ?
Depends, if you simply want an accurate wait, and not a periodic timer, this script is more ugly, because you need to code it in the timer callback.
But if you allow one more boolean "periodic" argument to the method start, sure it will be nicer.
 

Jesus4Lyf

Good Idea™
Reaction score
397
>if you simply want an accurate wait, and not a periodic timer, this script is more ugly, because you need to code it in the timer callback.
You need to in TU also, because you need to release the timer. In this returning true both pauses and releases the timer, so it makes no difference at all. Actually, this is nicer because you don't need to get the expiring timer to release it, etc.

So having a periodic boolean is redundant, because returning true takes care of it...

>the performance gain doesn't really matter
Well this system is actually slower than TU (25%). This system is just nice because it allows timer pausing. :)
 

emjlr3

Change can be a good thing
Reaction score
395
lets have a real benchmark - bench it with something like this (real world) - swap it out of using a struct stack, obviously

I am interested to see the speed difference then
 

Vexorian

Why no custom sig?
Reaction score
187
Everytime I see people use ExecCount to replace H2I I feel like jumping off the bridge.

You know that for timers there are much better ways to get rid of H2I? And not something that's awfully QUADRATIC in complexity?

And I mean, really, if you are an H2I-fobe, there are incredibly awesome ways to get rid of it they are also VERY old.
http://www.wc3c.net/pastebint.php?t=96865&code=3ca416c60f54bd6d7036e740d6616b74
http://www.wc3c.net/showthread.php?t=97993


Oh and it has an extra advantage over KT, this one actually works with long time intervals.
 

Jesus4Lyf

Good Idea™
Reaction score
397
>Everytime I see people use ExecCount to replace H2I I feel like jumping off the bridge.
Every time I see H2I-0x100000 considered "stable" without a second thought I feel like much the same.

>You know that for timers there are much better ways to get rid of H2I? And not something that's awfully QUADRATIC in complexity?
It's all handled within initialization - and if that's a problem, then so is TU Red, which only has any stability due to the very same. ExecCount is probably the best efficiency/stability balanced method of attaching to a trigger there is, so long as it's handled on init or something.

>there are incredibly awesome ways to get rid of it they are also VERY old.
Are they as efficient and stable? I know of modifying the period slightly, which isn't as efficient or stable, and I know of the method I used in KT2, which doesn't allow timer pausing.

>Oh and it has an extra advantage over KT, this one actually works with long time intervals.
That was solved months ago, I believe.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top