- Joined
- Nov 7, 2014
- Messages
- 571
Qalloc - fast instance allocation using a queue
Qalloc is similar to Nestharus's AllocFast and AllocQ but with 1 less variable, no save game corruption, without all the optional "extra" stuff, and with the observation that the difference in the allocation scheme is worthwhile only if the extra function call is eliminated, thus Qalloc uses textmacros.
example:
The call to the
The module also has a
The extra Q_SIZE (5 in the above example) argument helps with the cases in which one forgets to call deallocate at all, as opposed to calling deallocate more than once and getting a double free error.
example 2:
The benefit of using Qalloc instead of vJass's default implementation is only worthwhile for structs that are allocated and destroyed frequently, otherwise the default should be used.
Qalloc:
Qalloc is similar to Nestharus's AllocFast and AllocQ but with 1 less variable, no save game corruption, without all the optional "extra" stuff, and with the observation that the difference in the allocation scheme is worthwhile only if the extra function call is eliminated, thus Qalloc uses textmacros.
example:
JASS:
//! runtextmacro Qalloc("Foo", "5")
struct Foo extends array
implement Qalloc_Foo
implement Qalloc_Default_create_destroy
endstruct
The call to the
//! runtextmacro Qalloc("Foo", "5")
creates a private module called Qalloc_Foo
which declares a private member called qa__next
which is used for the implementation of allocate and deallocate.The module also has a
private static method onInit takes nothing returns nothing
that creates a queue of size 5 (in non-debug (release) mode this parameter is ignored and 8190 is used instead) at map init time.The extra Q_SIZE (5 in the above example) argument helps with the cases in which one forgets to call deallocate at all, as opposed to calling deallocate more than once and getting a double free error.
example 2:
JASS:
//! runtextmacro Qalloc("Bar", "3")
struct Bar extends array
implement Qalloc_Bar
string s // = "A" we lose the ability to have default values
static method create takes nothing returns thistype
local string s2 = "A"
// Qalloc_allocate must be called at the end of the locals block
//! runtextmacro Qalloc_allocate()
set this.s = s2
return this
endmethod
method destroy takes nothing returns nothing
local string s2 = this.s
// Qalloc_deallocate must be called after the locals block
//! runtextmacro Qalloc_deallocate()
endmethod
endstruct
The benefit of using Qalloc instead of vJass's default implementation is only worthwhile for structs that are allocated and destroyed frequently, otherwise the default should be used.
Qalloc:
JASS:
library Qalloc
public function panic takes string s returns nothing
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.0, 0.0, 60.0, s)
if 1 / 0 == 1 then // stop executing
endif
endfunction
// qa__next - we use this member to create a queue of all the indicies at map init time
// qa__next[0] - we use the 0th element as the head of the queue (its initial value is 1)
// we don't need a tail member because we add to the end of the queue in an "ad-hoc" way
// This textmacro must be called outside of a struct.
// Q_SIZE can have values in the range: 1 .. 8190
//
//! textmacro Qalloc takes STRUCT_NAME, Q_SIZE
private module Qalloc_$STRUCT_NAME$
static integer array qa__next
private static method onInit takes nothing returns nothing
local integer i = 1
loop
static if DEBUG_MODE then
exitwhen i >= $Q_SIZE$
else
exitwhen i >= 8190
endif
set qa__next[i] = i + 1
set i = i + 1
endloop
set qa__next[0] = 1
endmethod
endmodule
//! endtextmacro
// This textmacro must be called in the "create" method of a struct and at the end of the locals block.
//
//! textmacro Qalloc_allocate
local thistype this = qa__next[0]
static if DEBUG_MODE then
if this == 0 then
call Qalloc_panic("|cffFF0000[Qalloc_allocate] error: cannot allocate a thistype instance|r")
endif
endif
set qa__next[0] = qa__next[this]
debug set qa__next[this] = -1
//! endtextmacro
// This textmacro must be called in the "destroy" method of a struct after the locals block.
//
//! textmacro Qalloc_deallocate
static if DEBUG_MODE then
if qa__next[this] != -1 then
call Qalloc_panic("|cffFF0000[Qalloc_deallocate] error: double free for instance thistype(" + I2S(this) + ")|r")
endif
endif
set qa__next[this] = qa__next[0]
set qa__next[0] = this
//! endtextmacro
module Qalloc_Default_create_destroy
static method create takes nothing returns thistype
//! runtextmacro Qalloc_allocate()
return this
endmethod
method destroy takes nothing returns nothing
//! runtextmacro Qalloc_deallocate()
endmethod
endmodule
endlibrary