OneTimer map?

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
I was passing time and got the idea of a map which needs sereval timers but can run all of em on only one timer. I came up with this code. I know it could be better, thats why I'm posting it here. It would need Array recycling, I know.

I tested the code at low and high periods with sereval instances, no lag, no delay, no bugs.

JASS:

library OneTimer initializer init

    globals
        // At what period is recalls
        private constant real Period = 0.001
        // The global Timer
        private timer Timer = CreateTimer()
        // Instances Count
        private integer Count = 0
        // Globals array
        private integer array Counts
        private integer array Maxs
        private string array Names
    endglobals
    
    public function AddFunction takes string fctname, real period returns nothing
    // I know this will need recycling and to be re-done...
        set Names[Count] = fctname
        set Counts[Count] = 0
        set Maxs[Count] = R2I(period / Period)
        set Count = Count + 1
    endfunction
    
    private function Periodic takes nothing returns nothing
        local integer i = 0
        loop
            if (Counts<i> &gt;= Maxs<i>) then
                call ExecuteFunc(Names<i>)
                set Counts<i> = 0
            endif
            set Counts<i> = Counts<i> + 1
            exitwhen i == Count
            set i = i + 1
        endloop
    endfunction

    private function init takes nothing returns nothing
        call TimerStart(Timer, Period, true, function Periodic)
    endfunction
    
endlibrary
</i></i></i></i></i></i>


At 0.001, String leaks starts to make it laggy but it isn't the system at all thats lags...

JASS:

function First takes nothing returns nothing
    call BJDebugMsg(&quot;Instance : 0.50&quot;)
endfunction

function Second takes nothing returns nothing
    call BJDebugMsg(&quot;Instance : 1.00&quot;)
endfunction

function Third takes nothing returns nothing
    call BJDebugMsg(&quot;Instance : 1.50&quot;)
endfunction

function Fourth takes nothing returns nothing
    call BJDebugMsg(&quot;Instance : 2.00&quot;)
endfunction

function Fifth takes nothing returns nothing
    call BJDebugMsg(&quot;Instance : 2.50&quot;)
endfunction

function Sixth takes nothing returns nothing
    call BJDebugMsg(&quot;Instance : 3.00&quot;)
endfunction

function Seventh takes nothing returns nothing
    call BJDebugMsg(&quot;Instance : 3.50&quot;)
endfunction

function Eighth takes nothing returns nothing
    call BJDebugMsg(&quot;Instance : 4.00&quot;)
endfunction

function Nineth takes nothing returns nothing
    call BJDebugMsg(&quot;Instance : 4.50&quot;)
endfunction

function fast takes nothing returns nothing
    //call BJDebugMsg(&quot;FAST&quot;)
    // Because when it&#039;s working, it makes too many string leaks
    // and make map buggy as hell
endfunction

function InitTrig_test takes nothing returns nothing
    call OneTimer_AddFunction(&quot;fast&quot;, 0.001)
    call OneTimer_AddFunction(&quot;First&quot;, 0.50)
    call OneTimer_AddFunction(&quot;Second&quot;, 1.00)
    call OneTimer_AddFunction(&quot;Third&quot;, 1.50)
    call OneTimer_AddFunction(&quot;Fourth&quot;, 2.00)
    call OneTimer_AddFunction(&quot;Fifth&quot;, 2.50)
    call OneTimer_AddFunction(&quot;Sixth&quot;, 3.00)
    call OneTimer_AddFunction(&quot;Seventh&quot;, 3.50)
    call OneTimer_AddFunction(&quot;Eighth&quot;, 4.00)
    call OneTimer_AddFunction(&quot;Nineth&quot;, 4.50)
endfunction
 

Troll-Brain

You can change this now in User CP.
Reaction score
85
It's ugly because you have to use SCOPE_PREFIX/SCOPE_PRIVATE if your functions are public/private.
Also i didn't test myself but i've always heard that ExecuteFunc is several times slower than TriggerExecute/Evaluate ?
(Hmm i'm wondering if is not basically the same as CreateTrigger,AddAction,ExecuteTrigger,RemoveAction,DestroyTrigger)
Maybe it becomes slower and slower depends the number of functions declared inside the whole script ?

Sure, here you don't create handles, but i don't believe this thing win in speed against the same version but with TriggerAddCondition/Evaluate and a trigger array.

EDIT :
And you don't provide a way to link an integer data, which is very lame.
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
EDIT: Here it is: The Beta 0.5 version. I'll try doing what you said about TriggerExecute BUT does it means the the function periodic would have to return boolean if I use TriggerAddCondition? Could I use both TriggerAddAction / TriggerRemoveAction to avoid action leak?

Code

JASS:

// Some parts needs to be recoded for more efficienty.
// Thats why I post it here. Once it&#039;ll be almost perfect
// and as much efficient as possible, I&#039;ll post it for real.
library OneTimer initializer init

    globals
        // Maximun OneTimers there can be at once on the map.
        private constant integer MAX_TIMER_AT_ONCE = 100
        // Period of the timer
        private constant real Period = 0.001
        //The famous OneTimer
        private timer Timer = CreateTimer()
        // For the Struct return
        private integer StructId = 0
        private integer array Structs
        // Recycle
        private boolean array Used
    endglobals
    
    struct OneTimer
        private string name
        private integer max
        private integer count
        
        static method Create takes string s, real p returns integer
            local integer i = 0
            local thistype onetimer
            loop
                if not (Used<i>) then
                    set Used<i> = true
                    set onetimer = i
                    set onetimer.max = R2I(p / Period)
                    set onetimer.count = 0
                    set onetimer.name = s
                    return i
                endif
                exitwhen i == MAX_TIMER_AT_ONCE
                set i = i + 1
            endloop
            return -1
        endmethod
        
        method Release takes nothing returns nothing
            set Used[this] = false
            set .name = &quot;&quot;
            set .max = 0
            set .count = 0
        endmethod
        
        static method Periodic takes nothing returns nothing
            local integer i = 0
            local thistype onetimer
            loop
                if (Used<i>) then
                    set onetimer = i
                    if (onetimer.count &gt;= onetimer.max) then
                        call ExecuteFunc(onetimer.name)
                        set StructId = i
                        set onetimer.count = 0
                    endif
                    set onetimer.count = onetimer.count + 1
                endif
                exitwhen i == MAX_TIMER_AT_ONCE
                set i = i + 1
            endloop
        endmethod
    endstruct
    
    // Get the id of the current timered struct.
    
    public function SetData takes integer ot, integer data returns nothing
        set Structs[ot] = data
    endfunction

    public function GetData takes nothing returns integer
        return Structs[StructId]
    endfunction
    
    // Init
    
    private function init takes nothing returns nothing
        local integer i = 0
        loop
            set Used<i> = false
            exitwhen i == MAX_TIMER_AT_ONCE
            set i = i + 1
        endloop
        call TimerStart(Timer, Period, true, function OneTimer.Periodic)
    endfunction

endlibrary
</i></i></i></i>


Tested with

JASS:
 //Tested and worked
scope Test initializer init

    private struct data
        string name
    endstruct
    
    private function periodic takes nothing returns nothing
        local data d = OneTimer_GetData
        call BJDebugMsg(d.name)
    endfunction

    private function init takes nothing returns nothing
                                          // Only this need fixs. It could be considered has a con...
        local OneTimer ot = OneTimer.Create(&quot;Test__periodic&quot;, 0.05)
        local data d = data.create()
        set d.name = &quot;Hello GetTriggerUnit()&quot;
        call OneTimer_SetData(ot, d)
    endfunction
    
endscope
 

Romek

Super Moderator
Reaction score
964
This obsession with having as few timers as possible is becoming ridiculous.
The cost of having one timer running like this is simply incomparable to having those few extra timers running normally and efficiently.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Your one is same with Cohadar's TT.
However, your one is risky.

Jasshelper may compile private functions to :
[ljass]"Test__periodic"[/ljass]
or
[ljass]"Test___periodic"[/ljass]

That's why timer systems creators uses trigger to execute the functions, except for T32(because it is implemented in the scope, it can access the function by calling them)

If you continue to do this, the last you will get is worse edition of TT(Because you use very low period, which caused lag). Your one is incomparable with linked list, which is more efficient.

JASS:
////////////////////
//  TimedFunc v1.0
//   by kingking
//  StartPeriodic(func,data)
//  StopPeriodic()
///////////////////
library TimedFunc initializer Init
    
    globals
        constant real PERIOD = .03125
    endglobals
    
    function interface PeriodicFunc takes integer data returns nothing
    
    globals
        private PeriodicFunc array Func
        private integer array Data
        private integer array Prev
        private integer array Next
        private integer this = 0
        
        private integer Counter = 0
        private integer array NextNode
        private integer NextNodeCount = 0
    endglobals
    
    function StartPeriodic takes PeriodicFunc func, integer data returns nothing
        local integer i
        if NextNodeCount &gt; 0 then
            set i = NextNode[NextNodeCount]
            set NextNodeCount = NextNodeCount - 1
        else
            set Counter = Counter + 1
            set i = Counter
        endif
        set Prev[Next[0]] = i
        set Next<i> = Next[0]
        set Next[0] = i
        set Prev<i> = 0
        set Data<i> = data
        set Func<i> = func
    endfunction
    
    function StopPeriodic takes nothing returns nothing
        set Next[Prev[this]] = Next[this]
        set Prev[Next[this]] = Prev[this]
        set NextNodeCount = NextNodeCount + 1
        set NextNode[NextNodeCount] = this
    endfunction
    
    private function Handler takes nothing returns nothing
        set this = Next[0]
        loop
        exitwhen this == 0
            call Func[this].execute(Data[this])
            set this = Next[this]
        endloop
    endfunction
    
    private function Init takes nothing returns nothing
        call TimerStart(CreateTimer(),PERIOD,true,function Handler)
    endfunction
endlibrary
</i></i></i></i>
 

Romek

Super Moderator
Reaction score
964
@ kingkingyyk3:
Not only does it seem like you don't know what you're talking about, but the 'system' you posted does something quite different to what's described in the first post.
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
I won't publish it, I'll use it on my own.

Just want to know.
This version is leak-free, right?
It been improoved to use TriggerEvaluate and TriggerAddCondition(for leakfreeness)

JASS:
library OneTimer initializer init

    globals
        private constant integer MAX_TIMER_AT_ONCE = 100
        private constant real Period = 0.001
        private timer Timer = CreateTimer()
        private integer array Structs
        private boolean array Used
        private integer Id
    endglobals
    
    struct OneTimer
        private trigger trig
        private integer max
        private integer count
        
        static method Create takes code func, real p returns integer
            local integer i = 0
            local thistype ot
            loop
                if not (Used<i>) then
                    set Used<i> = true
                    set ot = i
                    set ot.max = R2I(p / Period)
                    set ot.count = 0
                    set ot.trig = CreateTrigger()
                    call TriggerAddCondition(ot.trig, Condition(func))
                    return i
                endif
                exitwhen i == MAX_TIMER_AT_ONCE
                set i = i + 1
            endloop
            return -1
        endmethod
        
        method Release takes nothing returns nothing
            set Used[this] = false
            call DestroyTrigger(.trig)
            set .trig = null
            set .max = 0
            set .count = 0
        endmethod
        
        method SetData takes integer data returns nothing
            set Structs[this] = data
        endmethod
        
        method GetData takes nothing returns integer
            return Structs[this]
        endmethod
        
        static method Periodic takes nothing returns nothing
            local integer i = 0
            local thistype ot
            loop
                if (Used<i>) then
                    set ot = i
                    if (ot.count &gt;= ot.max) then
                        set Id = i
                        call TriggerEvaluate(ot.trig)
                        set ot.count = 0
                    endif
                    set ot.count = ot.count + 1
                endif
                exitwhen i == MAX_TIMER_AT_ONCE
                set i = i + 1
            endloop
        endmethod
    endstruct
    
    public function GetTimer takes nothing returns OneTimer
        return Id
    endfunction
    
    private function init takes nothing returns nothing
        local integer i = 0
        loop
            set Used<i> = false
            exitwhen i == MAX_TIMER_AT_ONCE
            set i = i + 1
        endloop
        call TimerStart(Timer, Period, true, function OneTimer.Periodic)
    endfunction

endlibrary</i></i></i></i>

JASS:
scope Test initializer init

    private struct data
        string name
        integer count
    endstruct
    
    private function periodic takes nothing returns nothing
        local data d = OneTimer_GetTimer().GetData()
        set d.count = d.count + 1
        call BJDebugMsg(d.name + &quot; &quot; + I2S(d.count))
        if (d.count &gt; 500) then
            call OneTimer_GetTimer().Release()
        endif
    endfunction

    private function init takes nothing returns nothing
        local OneTimer ot = OneTimer.Create(function periodic, 0.05)
        local data d = data.create()
        set d.name = &quot;Hello, GetTriggerUnit-&quot;
        set d.count = 0
        call ot.SetData(d)
    endfunction

endscope
 

Romek

Super Moderator
Reaction score
964
Why would you want to use something like that, even if it's only for your private projects?
I'd strongly suggest T32 and TimerUtils, or KT2 if you'd rather an all-in-one system.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Not only does it seem like you don't know what you're talking about, but the 'system' you posted does something quite different to what's described in the first post.
It is just an example of linked list timer. It can be modified to fit GetTriggerUnit-'s stuffs.
I have tried the idea of GetTriggerUnit- before, however, the inefficient caused me to stay away from it.
 

Jesus4Lyf

Good Idea™
Reaction score
397
I'd strongly suggest T32 and TimerUtils, or KT2 if you'd rather an all-in-one system.
That's pretty much it, I'd say that's nearly perfect. I'd say T32/TU is the ultimate.

I also understand completely if you want to make your own sys anyway, regardless if it is best or not. There's a few issues with what you're doing. It's very inefficient. Your Create function is O(n). [LJASS]R2I(p / Period)[/LJASS] creates an inaccuracy (ok, it's small, but exists - think measuring unit backswing points). [LJASS]set ot.count = ot.count + 1[/LJASS] can be avoided, have a global that counts up in (gametime/period) as an integer. Saves a couple of array reads and math. :thup:

Hope that helps.
Go ahead, do what you will. ;)
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Omg, you are using DestroyTrigger. >< I think you need to read how TT works, then improve your one.
 

GetTriggerUnit-

DogEntrepreneur
Reaction score
129
Well, thank much much for your help guys.

I'll go with T32.

It's magical.

I'm working on a new snippet that uses T32 and Event (<3).

I love T32 because you don't need to SetData / GetData, only call .startPeriodic / stoPeriodic and implement it.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • Ghan Ghan:
    Still lurking
    +3
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      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