[snippet] AllocLoop (AKA Alloc 2)

Codes & Snippets

13 years
edited 8 years
Based on Alloc by Sevion, this version adds the possibility to make struct iteration. The idea of this snippet has credits for PurgeandFire.

In other words: this is Alloc version 1.09 with an extension to manage struct iterations. As a side note, this snippet is almost the core of PoC, and helped me to optimize the spell coding on it. So I ensure it works :)

Here's the code:

Code (jass) Select
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ AllocLoop ~~ by moyack ~~ Version 1.0 ~~ Variant version of...
//~~ Alloc ~~ By Sevion ~~ Version 1.09 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//  What is Alloc?
//         - Alloc implements an intuitive allocation method for array structs
//
//    =Pros=
//         - Efficient.
//         - Simple.
//         - Less overhead than regular structs.
//
//    =Cons=
//         - Must use array structs (hardly a con).
//         - Must manually call OnDestroy.
//         - Must use Delegates for inheritance.
//         - No default values for variables (use onInit instead).
//         - No array members (use another Alloc struct as a linked list or type declaration).
//
//    Methods:
//         - struct.allocate()
//         - struct.deallocate()
//
//           These methods are used just as they should be used in regular structs.
//
//    Modules:
//         - Alloc
//           Implements the most basic form of Alloc. Includes only create and destroy
//           methods.
//
//  Details:
//         - Less overhead than regular structs
//
//         - Use array structs when using Alloc. Put the implement at the top of the struct.
//
//         - Alloc operates almost exactly the same as default structs in debug mode with the exception of onDestroy.
//
//  How to import:
//         - Create a trigger named Alloc.
//         - Convert it to custom text and replace the whole trigger text with this.
//
//  Thanks:
//         - Nestharus for the method of allocation and suggestions on further merging.
//         - Bribe for suggestions like the static if and method names.
//         - PurgeandFire111 for some suggestions like the merging of Alloc and AllocX as well as OnDestroy stuff.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library Alloc   
    //! textmacro Alloc
        private static integer instanceCount = 0
        private thistype recycle
   
        static method allocate takes nothing returns thistype
            local thistype this
   
            if (thistype(0).recycle == 0) then
                debug if (instanceCount == 8190) then
                    debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to allocate too many instances!")
                    debug return 0
                debug endif
                set instanceCount = instanceCount + 1
                set this = instanceCount
            else
                set this = thistype(0).recycle
                set thistype(0).recycle = thistype(0).recycle.recycle
            endif

            debug set this.recycle = -1
   
            return this
        endmethod
   
        method deallocate takes nothing returns nothing
            debug if (this.recycle != -1) then
                debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to deallocate an invalid instance at [" + I2S(this) + "]!")
                debug return
            debug endif

            set this.recycle = thistype(0).recycle
            set thistype(0).recycle = this
        endmethod
    //! endtextmacro
   
    //! textmacro AllocLoop
        private static integer instanceCount = 0
        private thistype recycle
        thistype next
        thistype prev
   
        static method allocate takes nothing returns thistype
            local thistype this
   
            if (thistype(0).recycle == 0) then
                debug if (instanceCount == 8190) then
                    debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to allocate too many instances!")
                    debug return 0
                debug endif
                set instanceCount = instanceCount + 1
                set this = instanceCount
            else
                set this = thistype(0).recycle
                set thistype(0).recycle = thistype(0).recycle.recycle
            endif

            debug set this.recycle = -1
           
            set thistype(0).next.prev = this // "next" of head has our new instance as "previous"
            set this.next = thistype(0).next // "next" of our node is the "next" of head
            set thistype(0).next = this // "next" of head is now our node
            set this.prev = 0 // "previous" of our node is the head [this case, thistype(0)]
            return this
        endmethod
   
        method deallocate takes nothing returns nothing
            set .next.prev = .prev // set the "prev" of the "next" node to our "prev"
            set .prev.next = .next // set the "next" of the "prev" node to our "next"
           
            debug if (this.recycle != -1) then
                debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to deallocate an invalid instance at [" + I2S(this) + "]!")
                debug return
            debug endif

            set this.recycle = thistype(0).recycle
            set thistype(0).recycle = this
        endmethod
    //! endtextmacro
   
    module Alloc
        //! runtextmacro Alloc()
    endmodule
   
    module AllocLoop
        //! runtextmacro AllocLoop()
    endmodule
   
    // - This module must be used with "AllocLoop" textmacro
    // - this module must be pacled after a local definition in the code ALWAYS
    // - always use "this" as variable name
    module loop
        local thistype this = thistype(0).next
        loop
            exitwhen integer(this) == 0
    endmodule

    // this will end the looping code
    module endloop
            set this = this.next
        endloop
    endmodule
endlibrary


Comments are always welcome.
13 years
edited 13 years
Nice all-in-one snippet. :) I like it.

edit: If you wanna reduce one line, you can initialize this to thistype(0).recycle:
Code (jass) Select
    static method allocate takes nothing returns thistype
            local thistype this = thistype(0).recycle
   
            if (this == 0) then
                debug if (instanceCount == 8190) then
                    debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to allocate too many instances!")
                    debug return 0
                debug endif
                set instanceCount = instanceCount + 1
                set this = instanceCount
            else
                // this isn't needed then -> set this = thistype(0).recycle
                set thistype(0).recycle = this.recycle
            endif
13 years
Can i say this is ugly ?
13 years
It'd be better to just do a Linked List module that is statically instanced >.>.

In the create method, you'd add to the list. In destroy, you'd remove from the list.

Pretty simple.
13 years
Depends on what you need. There are static linked lists, circular linked lists, regular linked lists, heh.
13 years
textmacros + modules uses as textmacros == uber spaghetti code for speedfreaks.
There is nothing you can do about it, now i suppose i'm the only one here which hates these module usages, there are probably also "legion" of people on wc3c.net who share my opinion, but meh it's wc3c.net :p
13 years
Quote from: nestharus on August 20, 2012, 12:48:08 PM
Here is every simple collection you'll ever need
http://www.hiveworkshop.com/forums/submissions-414/std-collections-collections-221515/
LOVELY!!! checking nowww


Quote from: Troll-Brain on August 20, 2012, 01:25:05 PM
textmacros + modules uses as textmacros == uber spaghetti code for speedfreaks.
There is nothing you can do about it, now i suppose i'm the only one here which hates these module usages, there are probably also "legion" of people on wc3c.net who share my opinion, but meh it's wc3c.net :p
AQctually you can choose that suites the best for you: modules or texmacros.

13 years
Spaghetti code is spaghetti code.
Modules used as textmacros are textmacros with a different API but that's pretty much the same.
Speedfreak is speedfreak.

It's fine to try to optimize when it realy does matter and has a visible performance improvement, like recycle dummies units instead of create/destroy units, but here for me it's really overkill and makes no sense for the vJass code, that's really ugly in my opinion.
Not to mention that i hardly believe you will see any difference in performance.
13 years
Quote from: Purgeandfire on August 16, 2012, 12:12:26 AM
Nice all-in-one snippet. :) I like it.

edit: If you wanna reduce one line, you can initialize this to thistype(0).recycle:
Code (jass) Select
    static method allocate takes nothing returns thistype
            local thistype this = thistype(0).recycle
   
            if (this == 0) then
                debug if (instanceCount == 8190) then
                    debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to allocate too many instances!")
                    debug return 0
                debug endif
                set instanceCount = instanceCount + 1
                set this = instanceCount
            else
                // this isn't needed then -> set this = thistype(0).recycle
                set thistype(0).recycle = this.recycle
            endif


I did your suggestions and the system broke :( I'll remove the textmacros and left only modules.
13 years
I usually use arrays instead of the dot syntax :P

Anyway, this is not a bad resource.
It just reduces the amount of code you need to write.

And since the most common type of collection you'd need is a doubly linked list, then this could be pretty useful.
13 years
Quote from: Magtheridon96 on September 02, 2012, 11:18:17 PM
I usually use arrays instead of the dot syntax :P

Anyway, this is not a bad resource.
It just reduces the amount of code you need to write.

And since the most common type of collection you'd need is a doubly linked list, then this could be pretty useful.

Thanks for the approval. Love for ya :D