• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Timer Allocation

Status
Not open for further replies.
Want to avoid destroying timers? You can now do so with this snippet.

Introducing:

*TimerAlloc*

JASS:
library TimerAlloc
  
    private struct TimerAlloc extends array
        private static integer MAX_STACK = 500
        private static constant integer SUPER_MAX_STACK = 8000
      
        private static thistype current = 0
        private static thistype last = 0
        private thistype next
        private thistype recNext
      
        private timer TimerStack
      
        static method getTimerType takes timer t returns thistype
            local thistype this = thistype(0).next
            local integer i = 1
            loop
                exitwhen this.TimerStack == t or i == MAX_STACK
                set this = this.next
                set i = i + 1
            endloop
            if this.TimerStack != t then
                set this = last + 1
                set MAX_STACK = this
                set last.next = this
                set last = last.next
                set last.TimerStack = t
                set last.next = 0
            endif
            return this
        endmethod
      
        static method dealloc takes timer t returns nothing
            local thistype this = thistype.getTimerType(t)
            call PauseTimer(this.TimerStack)
            set this.recNext = recNext
            set recNext = this
        endmethod
      
        static method alloc takes nothing returns timer
            local thistype this
            if thistype(0).recNext == 0 then
                set current = current.next
                set this = current
            else
                set this = thistype(0).recNext
                set thistype(0).recNext = thistype(0).recNext.recNext
            endif
            return this.TimerStack
        endmethod
      
        private static method onInit takes nothing returns nothing
            local thistype i = 1
            loop
                set i.TimerStack = CreateTimer()
                call BJDebugMsg(I2S(i))
                set i.next = 0        //next[1] == next[0] = 0, next[2] == 0
                set thistype(0).next.next = i        //next[next[0]] == next[0] = 1, next[next[0]] == next[1] = 2
                set thistype(0).next = i            //next[0] = 1
                exitwhen i == MAX_STACK
                set i = i + 1
            endloop
            set last = i
            set thistype(0).next = 1    //Basically goes back to 1.
        endmethod
      
    endstruct
  
    function DeallocateTimer takes timer whichTimer returns nothing
        call TimerAlloc.dealloc(whichTimer)
    endfunction
    function AllocateTimer takes nothing returns timer
        return TimerAlloc.alloc()
    endfunction
  
endlibrary

A simple snippet of sorts, it allows you to use and recycle already created timers...

[At this point, this would be an unverified claim]

...so that you don't consume nearly as much memory as you do when creating timers and destroying them.
 
Last edited:
It looks like this library is underpowered. It does only what it is supposed to do, allocate a timer and if you return a timer that was not allocated, it would add that timer to the stack unless the number has already exceeded the maximum, which is SUPER_MAX_STACK.


I could try to integrate it with cinematics, but I'll have to fiddle a bit with cinematics before updating this library.


Scratch that, @Bribe already did that before.

[SECRET]
This is a secret.
[/SECRET]
 
Last edited:
Level 31
Joined
Jul 10, 2007
Messages
6,306
If you want to work with timers, there is another thing you can do. Timer merging. The current timer merging library seems to break native timers for some reason.


First, you start with a loop of timers that just always expire together. That is, you merge everything into one timer. This works for small periods.

JASS/script.j at master · nestharus/JASS · GitHub


For longer periods, you can implement one timer per start time and advance through a list on every timeout rather than use a hashtable and GetHandleId

timer 1 expires. Advance list. Current instance is the expired timer.


All timers with the same timeout would go on the list, new timers being added to the end of the list. If a timer is going to expire at around the same time as an existing timer, the code should just be appended to the existing timer and the list should be advanced an extra time (1 extra time per virtual timer placed on the native timer).


Now what Timer Tools does is it goes a step further. It uses both the quick timeout strategy and the long timeout strategy. It also supports multiple timer queues, one per long timeout.

Here are the results of all of these strategies being employed together

JASS:
Natives with Empty Function @7500 timers w/ various timeouts: 63.5 fps, range 61-64 fps
Natives with Data Attachment @7500 timers w/ various timeouts: 43-45 fps
Timer Tools Across 50 methods @7500 timers w/ various timeouts w/ data attachment: 63.5 fps, range 63-64 fps

Yes. The lib was actually faster than plain old native timers. Pretty crazy.

Here is the lib if you want to take this up and figure out what is wrong with it.

JASS/script.j at master · nestharus/JASS · GitHub
 
Okay, I'll take a look at it.

EDIT:

I have no words to describe the library I just read... (Woah :mind blown: )

The Timer struct is actually a collection of useful functions (basically a wrapper struct made available for everyone, except for destroy). It will take me a LOT of time just to understand, and reverse-engineer the code. Knowing your reputation, I will take it (assume) that your logic in coding these things is infallible, which it is.
 
Last edited:
Status
Not open for further replies.
Top