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

[vJASS] Global Alloc

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
Why use this over other Alloc?
- This module generates the least code possible in comparison to both the default vJass allocator and all the other Alloc, and uses only one variable for the whole map
- The default vJass allocator is not updated to the new JASS_MAX_ARRAY_SIZE


Alloc.j
JASS:
library Alloc /* v1.1.0 https://www.hiveworkshop.com/threads/324937/


    */uses /*

    */Table                 /*  https://www.hiveworkshop.com/threads/188084/

    */optional ErrorMessage /*  https://github.com/nestharus/JASS/blob/master/jass/Systems/ErrorMessage/main.j


    *///! novjass

    /*
        Written by AGD, based on MyPad's allocation algorithm

            A allocator module using a single global indexed stack. Allocated values are
            within the JASS_MAX_ARRAY_SIZE. No more need to worry about code bloats behind
            the module implementation as it generates the least code possible (6 lines of
            code in non-DEBUG_MODE), nor does it use an initialization function. This system
            also only uses ONE variable (for the whole map) for the hashtable.
    */
    |-----|
    | API |
    |-----|
    /*
      */module GlobalAlloc/*
            - Uses a single stack globally
      */module Alloc/*
            - Uses a unique stack per struct

          */debug readonly boolean allocated/* Is node allocated?

          */static method allocate takes nothing returns thistype/*
          */method deallocate takes nothing returns nothing/*

    *///! endnovjass

    /*===========================================================================*/

    globals
        private key stack
    endglobals

    static if DEBUG_MODE then
        private function AssertError takes boolean condition, string methodName, string structName, integer node, string message returns nothing
            static if LIBRARY_ErrorMessage then
                call ThrowError(condition, SCOPE_PREFIX, methodName, structName, node, message)
            else
                if condition then
                    call BJDebugMsg("[Library: " + SCOPE_PREFIX + "] [Struct: " + structName + "] [Method: " + methodName + "] [Instance: " + I2S(node) + "] : |cffff0000" + message + "|r")
                endif
            endif
        endfunction

        public function IsAllocated takes integer typeId, integer node returns boolean
            return node > 0 and Table(stack)[typeId*JASS_MAX_ARRAY_SIZE + node] == 0
        endfunction
    endif

    public function Allocate takes integer typeId returns integer
        local integer offset = typeId*JASS_MAX_ARRAY_SIZE
        local integer node = Table(stack)[offset]
        local integer stackNext = Table(stack)[offset + node]
        debug call AssertError(typeId < 0, "allocate()", Table(stack).string[-typeId], 0, "Invalid struct ID (" + I2S(typeId) + ")")
        if stackNext == 0 then
            debug call AssertError(node == (JASS_MAX_ARRAY_SIZE - 1), "allocate()", Table(stack).string[-typeId], node, "Overflow")
            set node = node + 1
            set Table(stack)[offset] = node
        else
            set Table(stack)[offset] = stackNext
            set Table(stack)[offset + node] = 0
        endif
        return node
    endfunction
    public function Deallocate takes integer typeId, integer node returns nothing
        local integer offset = typeId*JASS_MAX_ARRAY_SIZE
        debug call AssertError(node == 0, "deallocate()", Table(stack).string[-typeId], 0, "Null node")
        debug call AssertError(Table(stack)[offset + node] > 0, "deallocate()", Table(stack).string[-typeId], node, "Double-free")
        set Table(stack)[offset + node] = Table(stack)[offset]
        set Table(stack)[offset] = node
    endfunction

    module Alloc
        debug method operator allocated takes nothing returns boolean
            debug return IsAllocated(thistype.typeid, this)
        debug endmethod
        static method allocate takes nothing returns thistype
            return Allocate(thistype.typeid)
        endmethod
        method deallocate takes nothing returns nothing
            call Deallocate(thistype.typeid, this)
        endmethod
        debug private static method onInit takes nothing returns nothing
            debug set Table(stack).string[-thistype.typeid] = "thistype"
        debug endmethod
    endmodule

    module GlobalAlloc
        debug method operator allocated takes nothing returns boolean
            debug return IsAllocated(0, this)
        debug endmethod
        static method allocate takes nothing returns thistype
            debug call AssertError(Table(stack)[0] == (JASS_MAX_ARRAY_SIZE - 1), "allocate()", "thistype", JASS_MAX_ARRAY_SIZE - 1, "Overflow")
            return Allocate(0)
        endmethod
        method deallocate takes nothing returns nothing
            debug call AssertError(this == 0, "deallocate()", "thistype", 0, "Null node")
            debug call AssertError(Table(stack)[this] > 0, "deallocate()", "thistype", this, "Double-free")
            call Deallocate(0, this)
        endmethod
    endmodule


endlibrary

v1.1.0
- Uses Table instead of hashtable
- Added a GlobalAlloc module

v1.0.0
- Initial release
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
Good concept with some issues:

1) A global allocator should be using the same index and recycle stack and not a unique one for each struct instance. This allows to share a same basic root structure across all systems and make extension or collaboration simpler. This also avoids the need of a hashtable.
2) This can use a TableArray of size N (whereas N is the number of structs present in the map) instead of a full-on hashtable.
 

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
1. Could be useful but can have problems like a higher possibility of overtaking the max array index, in which case users are forced to use Table/hashtable.
Maybe another module as an addition would be better.
JASS:
library Alloc
...
private struct Node extends array
    implement Alloc
endstruct

module GlobalAlloc
    static method allocate takes nothing returns thistype
        return Node.allocate()
    endmethod
    method deallocate takes nothing returns nothing
        call Node(this).deallocate()
    endmethod
endmodule
endlibrary

2. Agree
 
Top