• 🏆 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!

[Solved] How to use Alloc?

Status
Not open for further replies.
So I need to give a timer (using TimerUtils) a unique instance, and I came across Alloc. Thing is, I have no idea how to use it :\ I'm not even sure that library does what I think it does

The way my timer is setup right now is that I have

local integer t_id as the index for the timer. I need to find out how to assign the unique number to this local variable so I can use it in the timer, and also recycle it once the timer is done.
 
Last edited by a moderator:
Isn't there a demo?

It should work like implementing alloc first, and then you can use the functions allocate() and deallocate()

implement Alloc

and then it should work.

I'm not even sure that library does what I think it does
struct's are inetgers. They get their unique inetger as index from their allocate() function
The deallocate() function recylces that integer again.

But the standard alloc function from structs is not best at performance and can be written better.
So some people came and wrote their own allocate and deallocate functions to get unique indices.

So basicly you use alloc if you don't want to use the stanard allocation function,
but actually it just returns an unique index for an array.
 
Level 22
Joined
Feb 6, 2014
Messages
2,466
It does what you want, it generates a unique id. You can write something like this at the bottom of the TimerUtils code
Add this to the TimerUtils library and add
" uses Alloc" (without quotes)
JASS:
library TimerUtils uses Alloc
//TimerUtils code
//...
//...
//add this
struct TimerUtilsId extends array
implement Alloc
//I'm not sure if static method create is necessary, but if it is, just make one
endstruct
endlibrary

When you want to allocate a new integer
JASS:
function MyFunction
    local timer t= NewTimer()
    local TimerUtilsId timerId = TimerUtilsId.allocate()
    call SetTimerData(t, timerId)
    //do your stuffs
    //Example
     call BJDebugMsg("Your unique id is " + I2S(timerId))
endfunction

And when you want to free that id,
JASS:
function Expire ...
    local timer t = GetExpiredTimer()
    local TimerUtilsId timerId = GetTimerData(t)
    call timerId.deallocate
endfunction

Here's a post explaining how allocation works
http://www.hiveworkshop.com/forums/2704955-post3.html
 
Last edited:
If you are not too familiar with structs, it's better to use the default alloc function, at least at start.

When a struct extends array, then it won't generate allocation and dealloacation functions, so then you one could use custom ones.

Edit:

Oh well, hm, if you only need a unique index, but no struct itself, then I would not use struct only for the alloc function, but rather deal with indexing by myself.
 
I literally only need a system that generates a unique number and recycles it when it's no longer needed (aka the timer has ended). I thought Alloc did that, but didn't realise it only worked with Structs.

One time I saw this text tag indexing method that looped through (i think) 1 to the highest index and then if a text tag was destroyed, it did another loop that went from the current number in the previous loop to the highest index and if the number didn't match it would increase everything + 1. Honestly I don't get it lol, which is why I was looking for a system that automated that entire mess for me.
 
Level 22
Joined
Feb 6, 2014
Messages
2,466
Have fun!


Directly copied from Nestharus' Alloc resource.
JASS:
library TimerIdAlloc initializer OnInit
    
    globals
        private integer array recycler
    endglobals
    
    function TimerIndexDeallocate takes integer id returns nothing
        set recycler[id] = recycler[0]
        set recycler[0] = id
    endfunction
    
    function TimerIndexAllocate takes nothing returns integer
        local integer id = recycler[0]
        if (recycler[id] == 0) then
            set recycler[0] = id + 1
        else
            set recycler[0] = recycler[id]
        endif
        return id
    endfunction
    
    private function OnInit takes nothing returns nothing
        set recycler[0] = 1
    endfunction
    
endlibrary



JASS:
scope Test initializer Init
    
    private function Expire takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer id = GetTimerData(t)
        call BJDebugMsg("Expired Timer Id = " + I2S(id))
        call TimerIndexDeallocate(id)
        call DestroyTimer(t)
        set t = null
    endfunction
    
    private function Test takes nothing returns nothing
        local integer i = 0
        local integer id
        local real time
        loop
            exitwhen i == 10
            set id = TimerIndexAllocate()
            set time = GetRandomReal(2.0, 5.0)
            call TimerStart(NewTimerEx(id), time, false, function Expire)
            call BJDebugMsg("Allocated Id = " + I2S(id) + " will expire in " + R2S(time) + " seconds")
            set i = i + 1
        endloop
    endfunction
    
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call BJDebugMsg("Pressed Esc to allocate ids to 10 timers")
        call TriggerRegisterPlayerEvent(t, Player(0), EVENT_PLAYER_END_CINEMATIC)
        call TriggerAddAction(t, function Test)
    endfunction
    
endscope
 

Attachments

  • Allocator.w3m
    24.1 KB · Views: 52
Level 31
Joined
Jul 10, 2007
Messages
6,306
Ok... so let's try to resolve all of the confusion.


Firstly, Alloc does exactly what you think it does. While it does run faster than the standard vJASS allocators and does generate less code, people do not mainly use it for performance reasons, but rather for its improved debugging capabilities. It can use a set of optional debugging libs to track memory. It can also do analysis for things like memory leaks : ). When writing very complex libs, this is an invaluable tool. Even if you don't care about using the debug utils yourself, if you are writing a resource that could be used by others, you should still opt for them so that others can debug things using your thing.

Next, a struct that extends an array is nothing but syntax decoration. Putting Alloc into this type of struct will just give you an allocator, which is exactly what you want.

JASS:
struct MyAllocator extends array
    implement Alloc
endstruct

function MyFunction takes nothing returns nothing
    local integer i = MyAllocator.allocate()
    call MyAllocator(i).deallocate()
endfunction


While this is unconventional, it can work. Normally, people would put variables within the struct so that they don't need to use ugly arrays. It just makes the code look nicer.

JASS:
myVariable[unitId] = 15
unitId.myVariable = 15


The post Flux had put up was just taking the basic allocation out of Alloc and putting it into a lib. The flavor used in that post is standard Alloc : ).



Finally, the reason Alloc seems to be confusing to use is because it's a macro that's made for use in structs. If you're not sure about macros, try playing with vjass textmacros a little bit to see what they do.



SpellBound, I hope I was able to clear up your confusion ^_-.


Fyi, here is likely what Flux's post should have been

JASS:
library TimerIdAlloc uses Alloc
    private struct Allocator extends array
        implement Alloc
    endstruct
    
    function TimerIndexDeallocate takes Allocator id returns nothing
        call id.deallocate()
    endfunction
    
    function TimerIndexAllocate takes nothing returns integer
        return Allocator.allocate()
    endfunction
endlibrary

Alternatively, we can go for a macro

JASS:
//! textmacro CREATE_ALLOCATOR takes NAME

scope $NAME$
    private struct Allocator extends array
        implement Alloc
    endstruct
    
    function $NAME$Deallocate takes Allocator id returns nothing
        call id.deallocate()
    endfunction
    
    function $NAME$Allocate takes nothing returns integer
        return Allocator.allocate()
    endfunction
endscope

//! endtextmacro

And to get the lib that Flux had written using the macro

JASS:
library TimerIdAlloc uses Alloc
    //! runtextmacro CREATE_ALLOCATOR("TimerIndex")
endlibrary
 
A message from the creator! *o*

I do understand it a bit better, but I'm one of those kind of people who understand something only after banging their head against the issue enough time for their brain to get in the proper shape for the understanding to sink it. It'll likely take me a while longer to really get the grasp of structs, but I suppose it's a start.

I'll try to read this through again when I have another instancing thing to do. Thanks :)
 
Status
Not open for further replies.
Top