Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

[Snippet] List Optimum Speed

Discussion in 'Graveyard' started by Nestharus, Sep 30, 2009.

  1. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Well, I gotta write documentation on the new API.

    Lists and list items are the exact same =). Push actually returns a new list item... the list item is whatever you want it to be.

    Now, the default list struct inside will be this-
    Code (vJASS):

    struct List
        implement List
        //! runtextmacro ListIterator("int", "integer")
    endstruct
     


    So if you wanted to set the data-
    Code (vJASS):

    set list.int = value
     


    Now, the reason for this is that List by itself has no idea what kind of data you will be using =). The default list includes an integer as a default type as well as a bundle of things for working with it.

    So in essence, you can create your own types of lists two ways-
    Code (vJASS):

    struct MyList extends List
    endstruct
     


    Code (vJASS):

    struct MyList
        implement List
    endstruct
     


    The list iterator methods would be this-
    Code (vJASS):

    //! runtextmacro ListIterator("name", "type")
     


    That will create a public var of type and name : |. It will also make a bundle of iterator methods for it.


    So, interestingly enough, if you wanted to test using every operation that other list pop and shift or w/e does =)
    Code (vJASS):

        set list.push.int = 15
       
        set var = list.pop.int
     


    The speed difference would be the array set =).
     
  2. aznricepuff

    aznricepuff

    Joined:
    Feb 22, 2006
    Messages:
    749
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    List and list items aren't the same. List are the nodes. People don't really care about the nodes. They care about the elements they put inside the nodes. Nobody would just call push() a bunch of times to get new List instances. They would also want to do
    set list.int = value
    .
     
  3. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    I edited it : P

    Is that ok for ya? =D

    Also, they can do
    Code (vJASS):

    set list.int = value
     


    Lol. It sets the int of the list to the value =P

    Look at my examples u >: O

    list.name = valueOfType
     
  4. aznricepuff

    aznricepuff

    Joined:
    Feb 22, 2006
    Messages:
    749
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    Ok, I just redid the test with the following code (for your List):

    a

    Code (vJASS):

    private function frontEndEnqueueList3 takes nothing returns real
        local integer stopWatch
        local integer i = 0
        local real time = 0.0
       
        set stopWatch = StopWatchCreate()
        loop
            exitwhen (i >= ELEMENT_COUNT)
            set list3 = list3.unshift()
            set list3.int = GetRandomInt(-0xfffffff, 0xfffffff)
            set i = i + 1
        endloop
        set time = StopWatchMark(stopWatch)
        call StopWatchDestroy(stopWatch)
        return time
    endfunction

    private function tailEndEnqueueList3 takes nothing returns real
        local integer stopWatch
        local integer i = 0
        local real time = 0.0
       
        set stopWatch = StopWatchCreate()
        loop
            exitwhen (i >= ELEMENT_COUNT)
            set list3 = list3.push()
            set list3.int = GetRandomInt(-0xfffffff, 0xfffffff)
            set i = i + 1
        endloop
        set time = StopWatchMark(stopWatch)
        call StopWatchDestroy(stopWatch)
        return time
    endfunction
     



    The results barely changed for the enqueues. Your list is still 1.5-2x slower (~0.030-0.040 sec vs. ~0.010-0.020 sec for mpt's List for 2k iterations).

    I still can't get dequeue or iteration to work for your List. Dequeue just doesn't work at all and when I try to iterate the loop always exits before I get to all 2000 elements. If you're wondering, my code is below:

    a

    Code (vJASS):

    private function frontEndDequeueList3 takes nothing returns real
        local integer temp
        local integer stopWatch
        local real time = 0.0
       
        set list3 = list3.getLast()
        set stopWatch = StopWatchCreate()
        loop
            exitwhen (list3.previous() == 0)
            set temp = List(list3.shift()).int
        endloop
        set time = StopWatchMark(stopWatch)
        call StopWatchDestroy(stopWatch)
        return time
    endfunction

    private function tailEndDequeueList3 takes nothing returns real
        local integer i = 0
        local integer temp
        local integer stopWatch
        local real time = 0.0
       
        set list3 = list3.getFirst()
        set stopWatch = StopWatchCreate()
        loop
            exitwhen (list3.next() == 0)
            set temp = List(list3.pop()).int
            set i = i + 1
        endloop
        set time = StopWatchMark(stopWatch)
        call StopWatchDestroy(stopWatch)
        return time
    endfunction

    private function iterateForwardList3 takes nothing returns real
        local integer temp
        local integer stopWatch
        local integer i = 0
        local real time = 0.0
       
        set stopWatch = StopWatchCreate()
        set list3 = list3.getFirst()
        loop
            exitwhen (list3.next() == 0)
            set list3 = list3.next()
            set temp = list3.int
        endloop
        set time = StopWatchMark(stopWatch)
        call StopWatchDestroy(stopWatch)
        return time
    endfunction

    private function iterateBackList3 takes nothing returns real
        local integer temp
        local integer stopWatch
        local real time = 0.0
       
        set stopWatch = StopWatchCreate()
        set list3 = list3.getLast()
        loop
            exitwhen (list3.previous() == 0)
            set list3 = list3.previous()
            set temp = list3.int
        endloop
        set time = StopWatchMark(stopWatch)
        call StopWatchDestroy(stopWatch)
        return time
    endfunction
     

     
  5. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Ok, I'm looking through MPT's list code...

    For iteration-
    impossible for MPT's list to compare with List Optimum Speed in speed, there's just no way from the reading to the setting it can't be done ><.

    add/remove-
    These actually move everything in the entire list o-o. Mine is pretty much same speed as push and unshift... add/remove is going to be insanely slow on MPT's list ><.

    push/unshift/pop/shift-
    Because the last element and the first element are always going to be the min and the max, these would actually be rather fast =). But as a result of this speed, add/remove are two useless methods that shouldn't even be used because of how slow they are (mass loops for the loss), so for pushing and unshifting, these should be about 1.5x faster I'd say, which works with your results as well.

    So, when it boils down to it, the winners are-
    add/remove (adding and removing of an arbitray list item):
    List Optimum Speed: not comparable...

    push/unshift/pop/shift (populating and remove first and last list items)-
    MPT's List: 1.5x to 2x faster

    iteration (reading and writing)-
    List Optimum Speed: 6x+ faster

    List Optimum Speed wins 2/3

    Pushing, unshifting, popping, and shifting are pretty important and are commonly used, but iteration is the most important thing. This is the reason you can't build a linked list off of a hashtable, that's a really bad idea. It's going to suck at iteration every time.
     
    Last edited: Oct 2, 2009
  6. aznricepuff

    aznricepuff

    Joined:
    Feb 22, 2006
    Messages:
    749
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    yes, I've seen your code. You've basically replicated how structs are allocated. So the only difference between this and using actual structs as nodes is that you bypass calls to constructors and destructors.

    However, you get into trouble with using this stack method just like with structs:

    Code (vJASS):

        call list.pop()
        set list2 = List.new()
        call list.next()
     


    If I happened to pop off the List that the variable list is pointing to...I'm screwed when I call list.next().

    And it doesn't matter that I'm calling GetRandomInt() in the test because I'm calling it for every list I'm testing. If I get rid of GetRandomInt(), your list will still be slower than mpt's.

    EDIT:

    Just did the test (front end enqueue) w/o GetRandomInt():

    yours: 0.29-0.37
    mpt's: 0.15-0.19

    Btw, your push has 7 array gets/sets and 1 boolean check. Mpt's has 1 array get, 1 array set, and one hashtable insertion. Benchmarks on wc3c put hashtable insertion at 1.5-2x slower than an array get, so his is the equivalent of 3.5-4 array get/sets.

    2ND EDIT:

    Btw, I noticed your shift and pop methods don't update the .previousIndex/.nextIndex of the new first/last nodes to 0. Moreover you don't reset .previousIndex and .nextIndex when you recycle your nodes. I fixed that and that finally got iteration working. Tail end dequeuing still refuses to work.
     
    Last edited: Oct 2, 2009
  7. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    I edited the previous post before u posted, so read it u =P

    list.pop() without any list item would put 0 into the freed indexes stack. The reason for this is that .list is never set for the master list because the master list is always .list. The only way to pop off a master list is to do .clean().

    Now, the issue here is that 0 is put into the freed indexes stack : |. That wouldn't cause a problem on the first use, but on the second use that'd be bad ^_^.

    Code (vJASS):

        call list.pop()
        set list2 = List.new()
        call list2.pop()
        set list3 = List.new()
        call list2.next()
     


    list3 would overwrite list2 thus causing a memory leak =). It would only happen every other use of .pop on an empty list.

    This would be considered the map maker's blunder, not mine ^_^. I could write a debug saftey check, but I'm never going to write a safety check that's always on =).

    Mine is still faster on add/remove and iteration, but you are right (I say this in previous post too) that pop/shift/push/unshift are slower =P.

    What's more important, actual iteration through data or populating first and last index?
     
  8. aznricepuff

    aznricepuff

    Joined:
    Feb 22, 2006
    Messages:
    749
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    Depends on what you are doing. If you are using it as a pure stack/queue (i.e. you just throw elements into the list and don't care about them until you remove) you're never going to iterate through the list at all. But if you are using it as some kind of...well...linked list (i.e. storing a bunch of event listeners to iterate through on events) then iteration becomes more important since the other stuff won't really need to be in real time.

    And about the pop thing I was talking about this:

    Code (vJASS):

        // list holds value of 5
        call list.pop() // the list's last node happens to be indexed 5, therefore index 5 is recycled and put into the allocation stack
        call List.new() // new() picks off the top index from the allocation stack, which is index 5. The node indexed 5 is now in a new list.
        call list.next() // I expect this to give me the next node in the original list (i.e. the one that popped a node off from two lines ago), but instead this gives me the next node in the new list (which should be 0) because list still holds the value 5.
     


    In actuality you didn't reset .nextIndex and .previousIndex when deallocating those indices (which caused more bugs) so technically the above wouldn't have caused any problems. But if I were to push something onto the new list before calling next() on list then the same problem arises.

    EDIT:

    By the way, mpt's list is actually a pseudo-array list with optimized addition/removal to the front and back of the list, not an actual linked list. And implementing a linked list using a hashtable doesn't slow down iteration by much...a hashtable search is 1.5-2x an array get. So you would have basically either 1.5-2x if you're saving elements directly into the hashtable or 2.5-3x if you're using the hashtable to save struct nodes. With direct array accessing it's going to be 2x: one for the array get for the next node and one for the array get to get w/e value you care about from the node.
     
  9. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    So I guess my linked list is the best possible implementation if you care about iteration

    MPT's is the best possible implementation if you care about population

    Now, on to the agenda-
    I'll break off the link ; ).

    list.pop-
    .previous.next = 0
    .previous = 0

    list.shift
    .next.previous = 0
    .next = 0

    Easy fixes easy fixes ^_^.


    By the way, add/remove is still super bad for MPT's list =P.
     
  10. aznricepuff

    aznricepuff

    Joined:
    Feb 22, 2006
    Messages:
    749
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    You would need to do it anytime you deallocate. Including in remove and clean (and btw, your clean was allowing index 0 to be put into the allocation stack...multiple times in fact). And

    Code (vJASS):

        // list holds value of 5
        call list.pop() // the list's last node happens to be indexed 5, therefore index 5 is recycled and put into the allocation stack
        call List.new() // new() picks off the top index from the allocation stack, which is index 5. The node indexed 5 is now in a new list.
        call list.next() // I expect this to give me the next node in the original list (i.e. the one that popped a node off from two lines ago), but instead this gives me the next node in the new list (which should be 0) because list still holds the value 5.
     


    Will always be a problem unless you separate the List structure from the nodes (i.e. not have a recursive definition of List).
     
  11. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Well, I'll fix up clean and clear ^_^, then it should be fine : D. And whenever I remove the first element or the last element, I'll be sure to break the active elements off from it.

    so pop and shift are fine in current version
    clear and clean will be fine soon =P

    And clean allowing index 0 to be put into the the stack multiple times... now that's odd o-o. Oh well, will all be fixed ^_^.

    I think everyone's also going to be happy with the new layout and with the new module too. This will include Collections, which are very simple and super fast pieces of data.

    Collections don't have any defined order, so they are really good when the order doesn't matter. The iteration should be a faster than this iteration speed (hard to believe huh).

    Collections will include-
    methods: push, pop, remove
    operators: [], []=, last

    In essence, this is the fastest possible thing there is.

    push adds to the top
    pop removes from the top and returns the value
    remove - removes a given index and returns the value. The removed index is set to the last index and the size is reduced.
    [] - translates into just Collection(index) or array[], which returns the actual value
    []= translates into set array[] = value
    last- translates into lastIndex

    This is code that I write all the time and is the exact same speed as an array with an added remove.

    Everything except for remove is inlined, which is ok. Remove in a cJASS version will be inlined as well : |. You can even do it by hand as all the elements will be public (remove is 3 lines).

    The overall code hit this will have is 11 lines-
    function, endfunction, 3 lines inside
    function, endfunction, 2 lines inside
    2 var lines

    In short, you can pretty much use this instead of an array every time if you don't care about order and it'll keep it indexed ^_^.

    If you remove the last element, then just do like .last = .last - 1 and that's it =).
    If you want the value, then get the value =P. Removing the last element is 2 lines, removing an inner element is 3 lines. Remove does not work on the last element =O.
     
  12. aznricepuff

    aznricepuff

    Joined:
    Feb 22, 2006
    Messages:
    749
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    Ok, as a future note, you don't need to explain everything you plan to update. When it's updated, it's updated, and people can see then what changed.

    Also, I don't think you understand what a queue is. You add things to the back of a queue and take things out from the front (FIFO), not add and remove both from the front (which would just be a stack).

    And please change the name of shift and unshift (I'd rather you change push and pop too but at least those are commonly used terms).

    Oh and personally I would rather have simpler code than brutal efficiency (i.e. if I can do it in one line rather than in 3 or in a way that makes way more sense intuitively at the cost of some speed, I would do it that way every time).
     
  13. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    List is done in single lines

    vJASS version of collection can't be single lines. It wouldn't be just a small loss of speed but a major loss : \. In a cJASS version, it would be possible to convert it into one line of code. Implementation would also look nicer =).

    Should I convert List Optimum Speed into cJASS? : o.
     
  14. aznricepuff

    aznricepuff

    Joined:
    Feb 22, 2006
    Messages:
    749
    Resources:
    4
    Maps:
    2
    Spells:
    1
    Tutorials:
    1
    Resources:
    4
    I don't like cJASS. I think trying to make JASS's syntax into C(++) is a bad idea. It's like if someone got tired of coding things in Ruby and decided to make a preprocessor to make syntax more like Java or C#. They're two completely different languages...don't try to force a language's syntax onto something else. cJASS is also nowhere near a standard...not even de facto (unlike vJASS). That being said, I will not accept pure cJASS scripts. If you want to include both a normal JASS/vJASS version and a cJASS version, that's fine though.
     
  15. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    That's how pretty much everyone feels =). Guess you'll just have to deal with the 2 calls then instead of 1 on Collections =). No way around it.

    Sweet New News ^^
    So, I've been working on the new release of List Optimum Speed. The latest release is all written in cJASS, but here's a peak at some of the features ^_-.


    Easier To Use/Better Collections-
    Collections can primarily be used to control struct allocation and deallocation for inlining and the ultimate performance ; ).

    Code (vJASS):

    struct C extends array {
        implement Collection

        public thistype create() {
            new Collection //inlined!
        }

        public void destroy() {
            destroy Collection //inlined!
        }
    }
     


    destroy can also take an index and even a struct name. new can also take a struct name and a var to be set to if you want to do some ini ; ).


    Statistic Lists-
    In short, these lists merge up common values into single list items. They don't maintain order, but they are rad fast and take up very little memory ; ).

    There are two types of statistical lists. First there are generated statistical lists. These lists are generated from plain lists. When it's generated, you can do quick analysis and so on. Generation is somewhat slow as a lot is done, but you could go through all values and get their indexes in the list and instances and so on ^_^. This uses hashtables.

    The other type is a plain statistic list. When you add new data into it, it stores it into an index for that data and increments the counter for that data by 1. Because it does this, it uses hashtables ^_-.


    IterateList-
    Iterate list is for special list operations-
    joining-
    joins two lists

    splicing-
    splices two lists

    cloning-
    clones a list (one value only, but you define the var)

    count-
    counts values of a list (you determine variable, it counts values of it)

    purge-
    removes all list items where variable equals value (you determine var, will cause issues with multiple vars)

    grep-
    get a list of values for a var from a given list. You determine the var and the filter.

    example:
    if List.GetFilterData > 6 {return true} return false


    Fun times

    The brand new c list implementation will be available soon : D, I just gotta debug it and possibly add sort. I'm still seriously debating sort. I also have to fix up a few things to prevent collisions (multiple collections within a struct), tie in collections with parent structures, and yea. I might also have to re-organize some of it, but so far looking fantastic. I'll probably ask for a group of volunteers to check it out before doing a public release (though I'm not yet sure where I'll release it).

    Maybe this awesome cJASS utility will give some incentive eh? : D.


    If there are any other features anyone's looking for, feel free to let me know ^_-. I don't think anyone else has actually done a grep command, so List Optimum Speed will probably be the only one with it : D.



    Of all the new features, grep and clone are probably the coolest : D. They use techniques that were initially designed in a framework called AGL.


    Here is an example of grep in action-
    Code (vJASS):

    library Test initializer Initialization {
        private struct MyList extends array {
            int data
            implement IterateList
        }
       
        trigger myFilter = CreateTrigger()
        trigger mySet = CreateTrigger()
        MyList myList1
        MyList myList2
       
        bool Filter() {
            if MyList.filter.data >= 4 && MyList.filter.data <= 12 {
                return true
            }
            return false
        }
       
        bool Clone() {
            MyList.cloneList.data = MyList.filter.data
            MyList.filter.remove() //just to show we can remove it if we wanted to
            return false
        }
       
        void Initialization() {
            TriggerAddCondition(myFilter, Condition(function Filter))
            TriggerAddCondition(mySet, Condition(function Clone))
            myList1 = MyList.create()
            myList1.push.data = 13
            myList1.push.data = 13
            myList1.push.data = 9
            myList1.push.data = 4
            myList1.push.data = 12
            myList1.push.data = 1042
            myList1.push.data = 6
            myList1.push.data = 4
            myList1.push.data = 1042
            myList1.push.data = 139
            myList2 = myList1.grep(myFilter, mySet)
        }
    }
     


    Still a few things that I need to fix over-all in the system. Some design issues really.

    1. If you remove an element via grep or splice or whatever from a given list and put it into another list, that other list is returned. The issue is you don't know which element is removed. If your list var was set to that element, suddenly you lose track of the list and the list is lost. In this way, I believe both lists have to be returned to ensure that you retain everything with a new operator-

    manipulated

    And it would work like this using the example from above-
    myList2 = myList1.grep(myFilter, mySet)
    myList1 = MyList.manipulated //returns the first index of the list that was acted on


    Another issue is if all list items from a given list are removed, the return value would be 0. Well, if a list is empty, a new list item is inserted ^_^. Lists cannot be empty, or the system just can't work : (. The reason is because initially, the system looks for a .list. Yes, I could put it into the list object in the background, but I split up the collections. Why? So that you could have more instances, 8191 total lists and 8191 total list items. Originally they were both the same sort of object, but yea... limited your instance count for no good reason : P.

    So that's the news everyone : D. Oh yea, and if you want to be a volunteer and get your hands on this system (the premier full out collections utility for JASS), uhm... let me kno kk : D.

    Collections 1.0 Pre-Release put up, the new face of List Optimum Speed in cJASS style
     
    Last edited by a moderator: Feb 5, 2010
  16. azlier

    azlier

    Joined:
    Oct 3, 2008
    Messages:
    353
    Resources:
    4
    JASS:
    4
    Resources:
    4
    The documentation is misleading. This isn't the fastest list ever. Sure, it may be the fastest list to have all those methods ever, but this still beats yours in speed:
    Code (vJASS):
    struct Node
        Node next
    endstruct


    Please fix your documentaion.
     
  17. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Sure thing ; ). I've been meaning to update the Collections lib, but I've wanted to make the update go through a preprocessing lib to increase efficiency and readability : ).
     
  18. azlier

    azlier

    Joined:
    Oct 3, 2008
    Messages:
    353
    Resources:
    4
    JASS:
    4
    Resources:
    4
    And you know what I hate most about this? I can't make the simplest of lists that use next and next= with it. Gah. There goes simplicity.
     
  19. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8
    Read that and decided to do another rewrite... it'll make this way more advanced and pro and offer more layers and will let you do exactly what you want to do =).

    So first rewrite offered more power and flexibility, but still didn't give quite enough to go down into the various operations.

    Here's an example of the power of this one >: o..

    Code (vJASS):

    /*Dynamic Memory
    ===================================================================
    Allocation:
    thisMemory = (freedMemorySpaceSize > 0) ? freedMemorySpace[--freedMemorySpaceSize] : memory++

    Deallocation:
    freedMemorySpace[freedMemorySpaceSize++] = thisMemory

    Beginner API:
        module DynamicMemoryStruct
            public static method new takes nothing returns thistype
            public method delete takes nothing returns nothing
           
    Standard API:
        module DynamicMemory
        module TryDynamicMemoryGetFreed
        module TryDynamicMemoryGetNew
        module CatchDynamicMemoryGet
        module TryFreeDynamicMemory
       
        module TryGetDynamicMemory
            implement TryDynamicMemoryGetFreed
            implement TryDynamicMemoryGetNew
            implement CatchDynamicMemoryGet

    Developer API:
        //! textmacro DYNAMIC_MEMORY takes NAMESPACE
        //! textmacro TRY_DYNAMIC_MEMORY_GET_FREED takes NAMESPACE, TO_MEMORY
        //! textmacro TRY_DYNAMIC_MEMORY_GET_NEW takes NAMESPACE, TO_MEMORY
        //! textmacro CATCH_DYNAMIC_MEMORY_GET takes RETURN_ERROR
        //! textmacro TRY_DYNAMIC_MEMORY_FREE takes NAMESPACE, FROM_MEMORY, RETURN_ERROR
    ===================================================================*/

     


    Dynamic or Recycled memory is normally used for instancing structs. As you can see you can go all the way down to declaring namespaces within your struct. The namespaces allow your structs to have different collections within them. The standard layer lets you work differently with previous freed or brand new instances or you can go with simplistic version, which is default. The simplest command just implements everything ; ).

    Edit
    Updating the List stuff isn't that big of a deal apparently, heh... just adding a few *very* simple elements...

    Code (vJASS):

    DEBUG_throwOverflowError
    DEBUG_throwOutOfBoundsError
    DEBUG_throwListOnlyOperationError
    DEBUG_throwNodeOnlyOperationError

    $NAMESPACE$TryTo

    PUSH takes NAMESPACE, PUSHED_NODE, NODE
    POP takes NAMESPACE, NODE
    UNSHIFT takes NAMESPACE, SHIFTED_NODE, NODE
    SHIFT takes NAMESPACE, NODE
     


    So really... you can construct w/e the heck you want : ). What you were asking for earlier Azlier was just so simple : (.
     
    Last edited: Feb 6, 2010
  20. Nestharus

    Nestharus

    Joined:
    Jul 10, 2007
    Messages:
    6,146
    Resources:
    8
    Spells:
    3
    Tutorials:
    4
    JASS:
    1
    Resources:
    8