Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
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.
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.
Oh... so not really useful for my purposes then? I mean if I'm not even using structs. I just need a way to obtain a unique index for my timers and recycle that number when the timer is done.
Alloc allows you to manage vjass structs easily. Is in fact my favourite code to manage complex systems in vJASS. I did a modification called allocloop which includes struct iterations easily.
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
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.
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
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
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
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.