• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[General] Single timer

Status
Not open for further replies.
Level 7
Joined
Apr 5, 2011
Messages
245
Use of constant single timer with .03 period with time counter that imitates a lot of timers with different periods

How much slow it would be? (Very slow, slow, quite fast)

Note that we already have to use time counters sometimes (or integer counters, does not really matter)
 
Level 7
Joined
Apr 5, 2011
Messages
245
Very slow.
Can't agree with you. 1 function call inside 0.03 timer already slower than counter. We still use a lot of functions.
Nestharus' TimerTools does that (iirc). It is certainly plausible--and it is very nice for mapmaking since it saves you from having multiple timers with similar periods when you only need 1.

EDIT: Almia beat me to the post.
Hmmm :ogre_hurrhurr:

Thanks!
 
Level 29
Joined
Oct 24, 2012
Messages
6,543

if u use one timer u would have to store the data in the time period on what u want to run at that time. An array is simply to small so u would have to use hashtable.

You need a 2D array for creating a One Map, One Timer system.

edit
dimf beat me to the number of posts ;_;

yup but u beat me to this.

Also what do u mean number of posts ?
 
Level 33
Joined
Apr 24, 2012
Messages
5,113
Think of it as creating a custom timer from a timer, and you will need to cache the following:
1) first, you need to create a list from a given timeout(E.g 0.03125 = new list, 0.05, new list)
2) Index a new custom timer to the given timeout's list
3) Cache the data of the custom timer

And, because of the mass list, you can hit the op limit.
It is like iterating a list of list and iterating that list's data :/
And also becoming slow because of calling Load Blah blah from hashtable

Btw, you can imagine one custom timer as this:
Timer[timeout][timerid]
 
Level 7
Joined
Apr 5, 2011
Messages
245
Here is my yesterday's code:
JASS:
//-=-=-=-=-=-=--=-=-=-=-=-=-=-=-
//-=-=-=-] QuantumTimer [-=-=-=-
//-=-=-=-=-=- v0.920 -=-=-=-=-=-

/*******************************************************
* Fields
*     readonly integer ExpiredTimer.data
*        - Returns data stored for the timer expired
* Functions
*     function SetWorldTimeSensitivity takes integer conglomerate returns integer
*        - Sets time sensitivity to quantum conglomerate (positive) / subquantum conglomerate (negative)
*     function GetWorldTimeSensitivity takes nothing returns integer
*        - Returns quantum conglomerate (positive) / subquantum conglomerate (negative)
*        ! Quantum conglomerate scales time rate by value / time by (1 / value)
*        ! Subquantum conglomerate scales time rate by (-1 / value) / time by -value
*     function StartTimer takes integer quantums, boolean periodic, boolexpr func, integer data returns integer
*        - Starts timer with specified configuration
*     function RemoveTimer takes integer timercode returns nothing
*        - Removes specified timer
*     function StopTimer takes integer timercode returns nothing
*        - Stops specified timer
*     function RestartTimer takes integer timercode returns nothing
*        - Restarts specified timer
*     function SetTimerData takes integer timercode, integer data returns nothing
*        - Set data for specified timer
*     function SetTimerTick takes integer timercode, integer quantums returns nothing
*        - Set tick quantum time for specified timer
*******************************************************/

library QuantumTimer initializer Init requires Indexer
//-=-=-=- Settings -=-=-=-
globals
    constant real TIME_QUANTUM = .03
    private constant integer MAX_TIMERS = 30
    private constant integer QUANTUMS_AVAILABLE = 2147483647
    private constant boolean SAFE = false
//-=-=-=-==-=-=-=-=-=-=-=-
    private integer Conglomerate
    private integer Count
    private boolean Pause
    private timer QuantumTimer
    private integer Indexer
    private integer array Quantums
    private boolean array Periodic
    private trigger array Trigger
    private integer array Data
    private integer array TriggerQuantum
    private integer WorkInteger
    private integer WorkInteger2
endglobals

    //! textmacro onExpireBegin takes increment, sign
        set Count = Count + $increment$
        static if SAFE then
            if Count > QUANTUMS_AVAILABLE then
                set Count = Count - QUANTUMS_AVAILABLE
            endif
        endif
        set WorkInteger = 0
        loop
            exitwhen WorkInteger == IndexCount(Indexer)
            if Trigger[WorkInteger] != null and TriggerQuantum[WorkInteger] $sign$ Count then
                set data = Data[WorkInteger]
    //! endtextmacro

    //! textmacro onExpireEnd
                if Periodic[WorkInteger] then
                    set TriggerQuantum[WorkInteger] = Count + Quantums[WorkInteger]
                    static if SAFE then
                        if TriggerQuantum[WorkInteger] > QUANTUMS_AVAILABLE then
                            set TriggerQuantum[WorkInteger] = TriggerQuantum[WorkInteger] - QUANTUMS_AVAILABLE
                        endif
                    endif
                else
                    call Deindex(Indexer, WorkInteger)
                    call TriggerClearConditions(Trigger[WorkInteger])
                endif
            endif
            set WorkInteger = WorkInteger + 1
        endloop
        if IndexCount(Indexer) == 0 then
            set Pause = true
            call PauseTimer(QuantumTimer)
        endif
    //! endtextmacro

    struct ExpiredTimer extends array
        readonly static integer data
        static method onQuantumConglomerateExpire takes nothing returns nothing
            //! runtextmacro onExpireBegin("Conglomerate", "<=")
                if Quantums[WorkInteger] > Conglomerate then
                    call TriggerEvaluate(Trigger[WorkInteger])
                else
                    set WorkInteger2 = Conglomerate / Quantums[WorkInteger]
                    if GetRandomInt(0, Quantums[WorkInteger] - 1) < Conglomerate - WorkInteger2 * Quantums[WorkInteger] then
                        set WorkInteger2 = WorkInteger2 + 1
                    endif
                    loop
                        call TriggerEvaluate(Trigger[WorkInteger])
                        exitwhen WorkInteger2 == 1
                        set WorkInteger2 = WorkInteger2 - 1
                    endloop
                endif
            //! runtextmacro onExpireEnd()
        endmethod
        static method onSubquantumConglomerateExpire takes nothing returns nothing
            //! runtextmacro onExpireBegin("1", "==")
                call TriggerEvaluate(Trigger[WorkInteger])
            //! runtextmacro onExpireEnd()
        endmethod
    endstruct
   
    //! textmacro Run
        if Pause and Conglomerate != 0 then
            set Pause = false
            if Conglomerate > 0 then
                call TimerStart(QuantumTimer, TIME_QUANTUM, true, function ExpiredTimer.onQuantumConglomerateExpire)
            else
                call TimerStart(QuantumTimer, -Conglomerate * TIME_QUANTUM, true, function ExpiredTimer.onSubquantumConglomerateExpire)
            endif
        endif
    //! endtextmacro
   
    function SetWorldTimeSensitivity takes integer conglomerate returns nothing
        if     conglomerate > 0 then
            call TimerStart(QuantumTimer, TIME_QUANTUM, true, function ExpiredTimer.onQuantumConglomerateExpire)
        elseif conglomerate < 0 then
            call TimerStart(QuantumTimer, -conglomerate * TIME_QUANTUM, true, function ExpiredTimer.onSubquantumConglomerateExpire)
        else
            if Pause == false then
                set Pause = true
                call PauseTimer(QuantumTimer)
            endif
        endif
        set Conglomerate = conglomerate
    endfunction

    function GetWorldTimeSensitivity takes nothing returns integer
        return Conglomerate
    endfunction

    //! textmacro Safe takes i
        static if SAFE then
            if $i$ > QUANTUMS_AVAILABLE then
                set $i$ = $i$ - QUANTUMS_AVAILABLE
            endif
        endif
    //! endtextmacro

    function StartTimer takes integer quantums, boolean periodic, boolexpr func, integer data returns integer
        set WorkInteger = Index(Indexer)
        set Quantums[WorkInteger] = quantums
        set TriggerQuantum[WorkInteger] = Count + quantums
        //! runtextmacro Safe("TriggerQuantum[WorkInteger]")
        set Periodic[WorkInteger] = periodic
        set Data[WorkInteger] = data
        if Trigger[WorkInteger] == null then
            set Trigger[WorkInteger] = CreateTrigger()
        endif
        call TriggerAddCondition(Trigger[WorkInteger], func)
        //! runtextmacro Run()
        return WorkInteger
    endfunction

    function RemoveTimer takes integer timercode returns nothing
        call Deindex(Indexer, timercode)
        call TriggerClearConditions(Trigger[timercode])
    endfunction

    function StopTimer takes integer timercode returns nothing
        set TriggerQuantum[timercode] = -1
    endfunction

    function RestartTimer takes integer timercode returns nothing
        set TriggerQuantum[timercode] = Count + Quantums[timercode]
        //! runtextmacro Safe("TriggerQuantum[timercode]")
        //! runtextmacro Run()
    endfunction

    function SetTimerData takes integer timercode, integer data returns nothing
        set Data[timercode] = data
    endfunction
   
    function SetTimerTick takes integer timercode, integer quantums returns nothing
        set Quantums[timercode] = quantums
    endfunction
   
    private function Init takes nothing returns nothing
        set Conglomerate = 1
        set Count = 1
        set Pause = true
        set Indexer = CreateIndexer(MAX_TIMERS)
        set QuantumTimer = CreateTimer()
    endfunction
endlibrary
So... I used loop for triggers :S
You saying ... this is bad and need something like ... large trigger array with conditions list? To prevent loop.
Or what array you are talking about

Edit:
Or you meant period array
 
Level 7
Joined
Apr 5, 2011
Messages
245
30 timers isn't enough.
0.03 is a bad timeout.
You can set 65533.
It's just recommended to use 2^n - 2, because my indexer uses first 2 on its own purpose
Also, because of the new rule established in Hive, new Timer systems will be insta-rejected.
Sorry for not saying this earlier.
Bad rule, I am going to improve and use this further :[

Edit:
it should be 0.031250000
Thanks, I'll fix it
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Ok, a long time ago, I tried making a 1 timer system. I actually tried making a few. I made the most efficient implementation possible for them and compared the performance. As the number of timers grow in a 1-timer system, the performance degrades. This is because it has to run off of a heap. It can't compete with a collection of timers that have lists of instances that have the same timeouts (as was done in another timer system that ran off of constant timeouts).

I've done timer systems for a few years and have written many. Of all of those, Timer Tools is the culmination of all of my work, taking everything I've learned from all of my attempts. It has the strengths of all of them and the weaknesses of none.

A one-timer system has already been proven to be fail on here. The fastest possible implementation was created.

You are wasting your time, srsly.

There is a reason that the rule exists ;)
 
Status
Not open for further replies.
Top