Snippet Data

Nestharus

o-o
Reaction score
84
note
Still working this out ><. Current design only has safety in debug for red, but red can crash the map if you have too many handles because it tries to be as fast as possible :\. It generates a pool of timers and groups at the start based on how many you specify as well. Actually, without safety red is just like TimerUtils orange :\. With safety, it might be slower than blue ><.

Uh... I just don't see how to make red version stable unless I do linked offsets.

Fast but optional Data Attachment for use with Recycle

In essence, this is very much like TimerUtils and so on, except that it goes through Recycle. It was split from Recycle to give two different venues for handle retrieval. Releasing a handle from here will automatically go through data attachment clearing in the release. Releasing a handle from Recycle won't.

Also, if you want to attach data to a given handle, you can use any handle in this. Next, you don't have to release a handle with attached data with this process. If you automatically initialize data, then it'd be better to release thru Recycle.

JASS:
library Data initializer Initialization uses Recycle
//settings
globals
    private constant boolean ATTACH_RED = true
    private constant boolean ATTACH_BLUE = false
    private constant boolean GLOBAL_GROUP = true
    private constant integer TIMER_POOL_SIZE = 350
    private constant integer GROUP_POOL_SIZE = 10
endglobals

/*Utility Information
//===================================================================
Name: Data
Version: 3.0
Author: Nestharus

Description:
    What does it do-
        Uses internal Recycle Vars for recycling handles and does data attachment
        
Requirements: Recycle- thehelper.net/forums/showthread.php?t=136087

Installation: NA

Variables:
------------------------------------------------------------------
ATTACH_RED-
    Similiar to TimerUtils red
    
ATTACH_BLUE-
    Similiar to TimerUtils blue
    
GLOBAL_GROUP-
    A global group for use in enumerations
    
TIMER_POOL_SIZE-
    How many timers for the timer pool to initially have
    
GROUP_POOL_SIZE-
    How many groups for the group pool to initially have

Functions:
------------------------------------------------------------------
*ONLY IF GLOBAL GROUP IS ENABLED*
-GetGroup()
    Returns a global group
    
-SetGroupData()
    Sets value in global group
    
-GetGroupData()
    Gets value from global group

-----------------------------------------------------------
-release(type h)
    Will release the type and stop it.
    
    DataTimer.release(h)
    DataGroup.release(h)
    
    ex-
    timer t = DataTimer.get()
    DataTimer.release(t)
-----------------------------------------------------------

*THESE ARE ONLY ENABLED IF ATTACH_RED OR ATTACH_BLUE ARE TRUE*
-setData(type var, integer value)
    Sets integer data on type
    
    DataTimer.setData(myTimer, 5)
    DataGroup.setData(myGroup, 5)

-getData(type var) returns integer
    Gets integer data on type
    
    local integer hello = DataTimer.getData(myTimer)
    local integer hello = DataGroup.getData(myGroup)
------------------------------------------------------------------*/
    globals
        private hashtable memory
        private integer handleIterator
        private group globalGroup
        private integer globalGroupData
        private integer handleId
        private integer offsetId
    endglobals
    
    function GetGroup takes nothing returns group
        return globalGroup
    endfunction
    
    function SetGroupData takes integer val returns nothing
        set globalGroupData = val
    endfunction
    
    function GetGroupData takes nothing returns integer
        return globalGroupData
    endfunction
    
    //! textmacro CREATE_DATA_STACK takes name, type, clean, create
        struct Data$name$ extends array
            private static delegate $name$ data$name$
            public static integer offset
            private static integer array data
            
            public static method setData takes $type$ var, integer value returns nothing
                static if ATTACH_RED
                    static if DEBUG_MODE then
                        if GetHandleId(var)-.offset &gt; 8191 then
                            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;ERROR - Attach: Too many handles.&quot;)
                            return
                        endif
                        if GetHandleId(var)-.offset &gt; 8191 then
                            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;More than one red offset, consider blue style&quot;)
                            return
                        endif
                    endif
                    set .data[GetHandleId(var)-.offset] = value
                endif
                static if ATTACH_BLUE
                    call SaveInteger(memory, GetHandleId(var), 0, value)
                endif
            endmethod
            
            public static method getData takes $type$ var returns integer
                static if ATTACH_RED
                    static if DEBUG_MODE then
                        if GetHandleId(var)-.offset &gt; 8191 then
                            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;ERROR - Attach: Too many handles.&quot;)
                            return 0
                        endif
                        if GetHandleId(var)-.offset &gt; 8191 then
                            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;More than one red offset, consider blue style&quot;)
                            return 0
                        endif
                    endif
                    return .data[GetHandleId(var)-.offset]
                endif
                static if ATTACH_BLUE
                    return LoadInteger(memory, GetHandleId(var), 0)
                endif
                return 0
            endmethod

            public static method release takes $type$ h returns nothing
                static if DEBUG_MODE then
                    if .index &gt; 8190 then
                        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;ERROR - Recycle: Overfilled recycle stack (8191 released objects)!&quot;)
                    endif
                    if h == null then
                        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;ERROR - Recycle: Freed null handle.&quot;)
                    endif
                    if GetHandleId(h)-.offset &gt; 8191 then
                        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;More than one red offset, consider blue style&quot;)
                        return
                    endif
                endif
                static if Recycle_AUTO_CLEAR then
                    $clean$
                endif
                set $name$[.index].handles = h
                set .index = .index + 1
                static if ATTACH_RED
                    static if DEBUG_MODE then
                        if GetHandleId(h)-.offset &gt; 8191 then
                            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;ERROR - Attach: Too many handles.&quot;)
                            return
                        endif
                    endif
                    set .data[GetHandleId(h)-.offset] = 0
                endif
                static if ATTACH_BLUE
                    call FlushChildHashtable(memory, GetHandleId(h))
                endif
            endmethod
        endstruct
    //! endtextmacro
    
    //! runtextmacro CREATE_DATA_STACK(&quot;Timer&quot;, &quot;timer&quot;, &quot;call PauseTimer(h)&quot;, &quot;CreateTimer()&quot;)
    //! runtextmacro CREATE_DATA_STACK(&quot;Group&quot;, &quot;group&quot;, &quot;call GroupClear(h)&quot;, &quot;CreateGroup()&quot;)
    
    private function Initialization takes nothing returns nothing
        static if GLOBAL_GROUP
            set globalGroup = CreateGroup()
        endif
        static if ATTACH_RED
            if GROUP_POOL_SIZE != 0 then
                set handleIterator = GROUP_POOL_SIZE-1
                set Group.index = GROUP_POOL_SIZE
                loop
                    set Group[handleIterator].handles = CreateGroup()
                    set handleIterator = handleIterator - 1
                    exitwhen handleIterator &lt; 0
                endloop
                set DataGroup.offset = GetHandleId(Group[Group.index-1].handles)
            endif
            if TIMER_POOL_SIZE != 0 then
                set Timer.index = TIMER_POOL_SIZE
                set handleIterator = TIMER_POOL_SIZE-1
                loop
                    set Timer[handleIterator].handles = CreateTimer()
                    set handleIterator = handleIterator - 1
                    exitwhen handleIterator &lt; 0
                endloop
                set DataTimer.offset = GetHandleId(Timer[Timer.index-1].handles)
            endif
        endif
        static if ATTACH_BLUE
            set memory = InitHashtable()
        endif
    endfunction
endlibrary
 

uberfoop

~=Admiral Stukov=~
Reaction score
177
ATTACH_RED-
Similiar to TimerUtils/GroupUtils red
First off, we must be familiar with a different 'GroupUtils', because the one I recognize has no flavors, or even an attachment system.

Second, it's not even similar to TU red. It's just scary. The safety is roughly equivalent to sprinting down a steep grassy hill covered in maple leaves and chipped obsidian spikes towards a lava pit in the rain.
 

Nestharus

o-o
Reaction score
84
2.0 is up. It now throws a set amount of timers/groups into the pools and it splits the pools.


350 timers should be enough for for timers that can have a wide variety of times.
50 groups should be enough groups

Timers are done after groups so that the timer limit is higher

The maximum is the maximum you can do in a single thread in wc3 without it crashing.

To reduce amount of timers used, use a system like KT2 for timers with common periods.

Edit
Introduced Global Group

I remembered how often I used a single group for an entire system and jesus4lyf's push for a global group standard, so here it is ; ).


And because I know this is going to happen, this does what TimerUtils should have done in my opinion ; ). Split up recycling and data attachment.
 

Jesus4Lyf

Good Idea™
Reaction score
397
>I remembered how often I used a single group for an entire system and jesus4lyf's push for a global group standard, so here it is ; ).
And you quite blatantly broke the standard, missed the point of it (that it didn't require a system or lib or any kind to be implemented) and dismissed that it was universally rejected by everyone.

You'd be better off defining your requirements before you write a system. What is this system meant to achieve? If we want TimerUtils optionally to be tacked onto Recycle, then Recycle should use static ifs to switch the timer recycling to TimerUtils if it exists instead. Then you don't require this new extra lib. It would be better encapsulation and better use of what things already are out there.

Of course, this will not work because it will not answer to the same interface. Recycle can never handle RED attachment, preloaded or not, because by definition the interface can accept the release of objects not created by the system (makes RED absolutely unstable). Changing this breaks backwards compatability, not changing this means you can't do handle offset attachment (thank God). Ok, so TU Red got away with it. Let's end it there, shall we?

As for blue, we can use hashtables ourselves... pretty sure we've accepted that hashtable wrappers don't qualify as systems (not that that's a concrete rule, but this ain't gonna fly).
 

Jesus4Lyf

Good Idea™
Reaction score
397
>fixed ;)
JASS:
library Data initializer Initialization uses Recycle
//settings
globals
    private constant boolean ATTACH_RED = true
    private constant boolean ATTACH_BLUE = false
    private constant boolean GLOBAL_GROUP = true
    private constant boolean SAFE_RED = true
    private constant integer TIMER_POOL_SIZE = 350
    private constant integer GROUP_POOL_SIZE = 50
endglobals

/*Utility Information
//===================================================================
Name: Data
Version: 4.0
Author: Nestharus

Description:
    What does it do-
        Uses internal Recycle Vars for recycling handles and does data attachment
        
Requirements: Recycle- thehelper.net/forums/showthread.php?t=136087

Installation: NA

Variables:
------------------------------------------------------------------
ATTACH_RED-
    Similiar to TimerUtils red
    
ATTACH_BLUE-
    Similiar to TimerUtils blue
    
GLOBAL_GROUP-
    A global group for use in enumerations
    
TIMER_POOL_SIZE-
    How many timers for the timer pool to initially have
    
GROUP_POOL_SIZE-
    How many groups for the group pool to initially have
    
SAFE_RED-
    Makes red handle up to 8191 handles safely at a performance hit

Functions:
------------------------------------------------------------------
*ONLY IF GLOBAL GROUP IS ENABLED*
-GetGroup()
    Returns a global group
    
-SetGroupData()
    Sets value in global group
    
-GetGroupData()
    Gets value from global group

-----------------------------------------------------------
-release(type h)
    Will release the type and stop it.
    
    DataTimer.release(h)
    DataGroup.release(h)
    
    ex-
    timer t = DataTimer.get()
    DataTimer.release(t)
-----------------------------------------------------------

*THESE ARE ONLY ENABLED IF ATTACH_RED OR ATTACH_BLUE ARE TRUE*
-setData(type var, integer value)
    Sets integer data on type
    
    DataTimer.setData(myTimer, 5)
    DataGroup.setData(myGroup, 5)

-getData(type var) returns integer
    Gets integer data on type
    
    local integer hello = DataTimer.getData(myTimer)
    local integer hello = DataGroup.getData(myGroup)
------------------------------------------------------------------*/
    globals
        private hashtable memory
        private integer handleIterator
        private group globalGroup
        private integer globalGroupData
        private integer handleId
        private integer offsetId
    endglobals
    
    function GetGroup takes nothing returns group
        return globalGroup
    endfunction
    
    function SetGroupData takes integer val returns nothing
        set globalGroupData = val
    endfunction
    
    function GetGroupData takes nothing returns integer
        return globalGroupData
    endfunction
    
    //! textmacro CREATE_DATA_STACK takes name, type, clean, create
        struct Data$name$ extends array
            private static delegate $name$ data$name$
            public static integer array offset
            private static integer array data
            
            public static method setData takes $type$ var, integer value returns nothing
                static if ATTACH_RED
                    static if SAFE_RED
                        handleId = GetHandleId(var)
                        offsetId = 0
                        loop
                            if .offset[offsetId] == 0 then
                                set .offset[offsetId] = handleId
                            endif
                            exitwhen handleId-.offset[offsetId] &lt; 8191
                            set offsetId = offsetId + 1
                        endloop
                    endif
                    static if Recycle_DEBUG and not SAFE_RED then
                        if GetHandleId(var)-.offset[0] &gt; 8191 then
                            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;ERROR - Attach: Too many handles.&quot;)
                            return
                        endif
                    endif
                    static if SAFE_RED
                        set .data[handleId-.offset[offsetId]] = value
                    else
                        set .data[GetHandleId(var)-.offset[0]] = value
                    endif
                endif
                static if ATTACH_BLUE
                    call SaveInteger(memory, GetHandleId(var), 0, value)
                endif
            endmethod
            
            public static method getData takes $type$ var returns integer
                static if ATTACH_RED
                    static if SAFE_RED
                        handleId = GetHandleId(var)
                        offsetId = 0
                        loop
                            if .offset[offsetId] == 0 then
                                set .offset[offsetId] = handleId
                            endif
                            exitwhen handleId-.offset[offsetId] &lt; 8191
                            set offsetId = offsetId + 1
                        endloop
                    endif
                    static if Recycle_DEBUG and not SAFE_RED then
                        if GetHandleId(var)-.offset[0] &gt; 8191 then
                            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;ERROR - Attach: Too many handles.&quot;)
                            return 0
                        endif
                    endif
                    static if SAFE_RED
                        return .data[handleId-.offset[offsetId]]
                    else
                        return .data[GetHandleId(var)-.offset[0]]
                    endif
                endif
                static if ATTACH_BLUE
                    return LoadInteger(memory, GetHandleId(var), 0)
                endif
                return 0
            endmethod

            public static method release takes $type$ h returns nothing
                static if SAFE_RED
                    handleId = GetHandleId(h)
                    offsetId = 0
                    loop
                        if .offset[offsetId] == 0 then
                            set .offset[offsetId] = handleId
                        endif
                        exitwhen handleId-.offset[offsetId] &lt; 8191
                        set offsetId = offsetId + 1
                    endloop
                endif
                static if Recycle_DEBUG and not SAFE_RED then
                    if h == null then
                        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;ERROR - Recycle: Freed null handle.&quot;)
                    endif
                    if .index &gt; 8190 then
                        call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;ERROR - Recycle: Overfilled recycle stack (8191 released objects)!&quot;)
                    endif
                endif
                static if Recycle_AUTO_CLEAR then
                    $clean$
                endif
                set $name$[.index].handles = h
                set .index = .index + 1
                static if ATTACH_RED
                    static if Recycle_DEBUG then
                        if GetHandleId(h)-.offset &gt; 8191 then
                            call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, &quot;ERROR - Attach: Too many handles.&quot;)
                            return
                        endif
                    endif
                    static if SAFE_RED
                        set .data[handleId-.offset[offsetId]] = 0
                    else
                        set .data[GetHandleId(h)-.offset[0]] = 0
                    endif
                endif
                static if ATTACH_BLUE
                    call FlushChildHashtable(memory, GetHandleId(h))
                endif
            endmethod
        endstruct
    //! endtextmacro
    
    //! runtextmacro CREATE_DATA_STACK(&quot;Timer&quot;, &quot;timer&quot;, &quot;call PauseTimer(h)&quot;, &quot;CreateTimer()&quot;)
    //! runtextmacro CREATE_DATA_STACK(&quot;Group&quot;, &quot;group&quot;, &quot;call GroupClear(h)&quot;, &quot;CreateGroup()&quot;)
    
    private function Initialization takes nothing returns nothing
        static if GLOBAL_GROUP
            set globalGroup = CreateGroup()
        endif
        static if ATTACH_RED
            static if GROUP_POOL_SIZE &gt; 0
                set handleIterator = GROUP_POOL_SIZE-1
                set Group.index = GROUP_POOL_SIZE
                loop
                    set Group[handleIterator].handles = CreateGroup()
                    set handleIterator = handleIterator - 1
                    exitwhen handleIterator &lt; 0
                endloop
                set DataGroup.offset[0] = GetHandleId(Group[Group.index-1].handles)
            endif
            static if TIMER_GROUP_SIZE &gt; 0
                set Timer.index = TIMER_POOL_SIZE
                set handleIterator = TIMER_POOL_SIZE-1
                loop
                    set Timer[handleIterator].handles = CreateTimer()
                    set handleIterator = handleIterator - 1
                    exitwhen handleIterator &lt; 0
                endloop
                set DataTimer.offset[0] = GetHandleId(Timer[Timer.index-1].handles)
            endif
        endif
        static if ATTACH_BLUE
            set memory = InitHashtable()
        endif
    endfunction
endlibrary
I bet SAFE_RED is slower than BLUE.
 

Nestharus

o-o
Reaction score
84
Still needs some work def, but I'm sure I can tweak it. About only way for SAFE_RED to work is through the loop. It's nice that it only happens every 8191 handles on the map, but still, a loop has to be done.

That's only way I can think of to d 100% safe red style.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
JASS:
                        loop
                            if .offset[offsetId] == 0 then
                                set .offset[offsetId] = handleId
                            endif
                            exitwhen handleId-.offset[offsetId] &lt; 8191
                            set offsetId = offsetId + 1
                        endloop


This is slower than ABC. I have an idea with this for a month ago. I wrote the attach system with this. In mass of usage, about 200 threads, this little thingy starts to lag. But in ABC, it did not lag.
 

Nestharus

o-o
Reaction score
84
Why would you even use this. >_<
TU Red is better, no objections?

Actually, like I said..

unsafe mode is exactly like TU Oj (without the bundle of ifs to prevent game crash)

If I got rid of subtracting based on first var, it'd be exactly like TU Red, lol (without the ifs)

Plus this ties in with Recycle (the point I made it). TU uses its own stuff :\.

People keep griping for safety though, and if they want safety they have to use hashtables because non-hashtable is always going to have limits, and when you hit those limits map will crash ><.

This is slower than ABC. I have an idea with this for a month ago. I wrote the attach system with this. In mass of usage, about 200 threads, this little thingy starts to lag. But in ABC, it did not lag.

Uh... I don't think you read it right because there's no way it could lag with 200 triggers running unless you had like... 100,000 handles.

It only ever gets a new offset every 8192 handles.

Actually, now that i think about it, SAFE would break because ids would collide ; ), and there's no way to fix that ;o, lol. I guess the best I can do here is orange style, which still has a definite limit. RED_SAFE was utterly pointless anyways.
 

Hatebreeder

So many apples
Reaction score
381
Why do you make use of In-Game HashTables?

It's slower than a simulated one, if I remember correctly =X
Thuss, why not just use Jesus Hash function? It's faster and, thats what you want to achieve, right?

Plus, why would I want to use this, if I got something like KT/TT?
It makes everything run on a Highspeed timer and also has function for user defined periods PLUS it runs everyting on just one Timer... Which is more efficient, I suppose.

I see alot of improvements have to be made =X
 

Azlier

Old World Ghost
Reaction score
461
>Thuss, why not just use Jesus Hash function?

Hashtables have beaten Jesus' hashing, so they're actually pretty good.

>PLUS it runs everyting on just one Timer

KT2 uses multiple timers. It's very fast for low periods, but for smooth effects (which is often what low period timers are for) T32 is better.

TimerUtils beats KT2 with periods above 0.3 or something.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top