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

[vJASS] Is Struct Instance Allocated

Discussion in 'Triggers & Scripts' started by masterofra, Apr 20, 2013.

  1. masterofra

    masterofra

    Joined:
    Mar 22, 2009
    Messages:
    170
    Resources:
    0
    Resources:
    0
    I have a struct started here. I need to determine if an instance of a struct was actually created, and hence exists.
    I can see a way to do this, but I want to know if there is an intrinsic method of doing it.

    I would add an extra member variable, isAllocated. Set it to true when creating, false when destroying.
    However, considering that the struct stack doesn't grow until it hits the 8191 limit, even when you destroy one in the middle of the stack, (I guess its not a stack, but still) there must be something in the resulting code that determines if an index is in use or not.

    Basically, is there a way to ask an instance of a struct if it exists?
    Also, what does comparing an instance of a struct with null do? Or -1? I've seen both, and am unsure.
    Code (vJASS):
    struct PlayerData
       
        static method operator[] takes integer iIndex returns PlayerData
            local PlayerData this = iIndex + 1
            return this
        endmethod
        static method create takes player iPlayer returns PlayerData
            local PlayerData this = PlayerData.allocate()
           
            return this
        endmethod
       
    endstruct
     
    Last edited: Apr 21, 2013
  2. HerrStanev

    HerrStanev

    Joined:
    Mar 27, 2013
    Messages:
    9
    Resources:
    0
    Resources:
    0
    Compare it to 0? Existing struct instances start from 1.
     
  3. deathismyfriend

    deathismyfriend

    Joined:
    Oct 24, 2012
    Messages:
    6,526
    Resources:
    14
    Spells:
    12
    Tutorials:
    2
    Resources:
    14
    the thing that tells what struct index the struct is assigned is in the allocate method.

    also u should learn the
    Code (vJASS):
    thistype
    keyword

    if u want to get this integer just set tempInt = this
    this is the indexed struct number
     
  4. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,174
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    You could add a boolean struct member, and set it to true when allocating the instance. Set it to false when deallocation

    Code (vJASS):

    struct asdf
        boolean isAllocated

        static method newInstance takes nothing returns thistype
            local thistype this = thistype.allocate()
            set this.isAllocated = true
            return this
        endmethod

        method isIndexAllocated takes nothing returns boolean
            return this.isAllocated
        endmethod
        // Or static method
        static method isIndexAllocated takes integer i returns boolean
            local thistype this = i
            return this.isAllocated
        endmethod
    endstruct
     
     
  5. masterofra

    masterofra

    Joined:
    Mar 22, 2009
    Messages:
    170
    Resources:
    0
    Resources:
    0
    @HerrStanev I know. What I don't know is what comparing it to null does. After all, null is usually refering to a null pointer(c++), or rather a null handle, which applies to units and locations, not integers. However, it can manage it fine, so I want to know whether null is a 0 or -1.

    @deathismyfriend I already know all of that. I never used the thistype keyword unless in a module. I am pretty sure it is, when parsed, replaced with the correct name, and hence doesn't really matter.
    I looked at the parsed code in this thread. http://www.hiveworkshop.com/forums/jass-ai-scripts-tutorials-280/coding-efficient-vjass-structs-187477/
    But I cannot determine how it works, or what I could compare to determine whether or not an instance has been allocated yet or not.

    I know struct instances are integers under the hood.

    @Maker I already know of that easy method of doing it. I was asking about whether there was an innate method of doing it, before adding an unnecessary member variable.

    Not sure if I communicated the problem correctly.

    The question is: Without adding any extra method or variables or w.e., Can I do something to determine if a particular instance of a struct has been allocated (had .create run and returned that instance, and hasn't yet been .destroy() -ed)
    If I were to, like in my code above, set my struct instance to a particular value,
    Code (vJASS):

            local PlayerData this = iIndex + 1
     

    I would want to make sure that this actually exists.

    For now, I am going to just use the extra boolean variable. It really does seem wrong to me tho.
     
  6. deathismyfriend

    deathismyfriend

    Joined:
    Oct 24, 2012
    Messages:
    6,526
    Resources:
    14
    Spells:
    12
    Tutorials:
    2
    Resources:
    14
    if ur looking for an allocator u can always use nestharus's module. http://www.hiveworkshop.com/forums/jass-resources-412/snippet-alloc-alternative-221493/
    just put it in a library and do this
    Code (vJASS):
    struct test extends array
            implement Alloc
        endstruct
     


    im not sure if that is what u want this may also be a solution. i use this to check for structs.
    Code (vJASS):

        method isStruct takes nothing returns boolean
            return this != 0
        endmethod
     

    if this doesnt equal 0 then it is a struct
     
  7. Zwiebelchen

    Zwiebelchen

    Joined:
    Sep 17, 2009
    Messages:
    7,014
    Resources:
    12
    Models:
    5
    Maps:
    1
    Spells:
    1
    Tutorials:
    1
    JASS:
    4
    Resources:
    12
    I think comparing the struct to 0 works.
    However, if you must check for a struct to exist or not in order to do something, you have a design flaw in your system concept, as all databases should only contain actual "existing" data and be cleared of the struct as soon as it's deallocated.
    If you need to check wether your struct exists or not, you probably use an O(n) search/recycler algorythm, which is not effective. You can always have a table with lookup and reverse lookup functionality for O(1) array searches.

    Memory in WC3 is cheap. Don't hesitate to use a dedicated table just for storing the reverse lookup data (get the array index by object vs. get object by array index).
     
  8. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,429
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    It might not always work. Consider this case:
    Code (vJASS):
    struct X
        method A takes nothing returns nothing
            call this.destroy()
            call BJDebugMsg(I2S(this)) // should display a value != 0
        endmethod

        static method create takes nothing returns thistype
            local thistype this = thistype.allocate()
            call this.A()
            return this
        endmethod
    endstruct


    Unless my logic is incorrect (which happens quite often). My reasoning is that when
    this
    is passed to a function the variable will refer to whatever integer
    this
    holds. When you destroy/deallocate
    this
    , the recycling is handled in the background but the variable
    this
    still holds whatever integer value it held before. This, of course, is because the integers aren't really "destroyed", they are just reassigned (or in the case of structs, the value of "this" just shifts to the front of the stack to be the next index to be used). When that value is reassigned, the former remains the same. ex: y = 5; x = y; y = 6; x still equals 5.

    When a struct is used it has a particular variable set to -1. When it is destroyed, the struct instance is moved to the front of the "freed index stack" (indexes that are destroyed/no longer used, so that they can be reused) and then that variable (the one that is equal to -1) is set to the next index in the stack. However, you can't access these variables. Technically, you could check if something was destroyed by checking if that variable is != -1, but you would have to use custom allocation.

    Since that is a bit of a hassle (it is still an option though), I would just use a custom member. :)
     
  9. deathismyfriend

    deathismyfriend

    Joined:
    Oct 24, 2012
    Messages:
    6,526
    Resources:
    14
    Spells:
    12
    Tutorials:
    2
    Resources:
    14
    if this doesnt work like that then y not set this to 0 in ur destroy function to make it work ?
     
  10. Tirlititi

    Tirlititi

    Joined:
    Jul 11, 2010
    Messages:
    396
    Resources:
    12
    Models:
    6
    Maps:
    2
    Spells:
    3
    JASS:
    1
    Resources:
    12
    There is a double-free protection in vjass structures (which means that
    .destroy()
    check if the instance is valid or not) so there is an internal way of doing it.

    However, it uses a special integer variable and I don't think it is supposed to be used by the coder.
    Here is a sample of what you may do, but it's kinda dirty :
    Code (vJASS):
    struct PlayerData
       
        static method operator[] takes integer iIndex returns PlayerData
            local PlayerData this = iIndex + 1
            return this
        endmethod
        static method create takes player iPlayer returns PlayerData
            local PlayerData this = PlayerData.allocate()
           
            return this
        endmethod

        method isValid takes nothing returns boolean
            return si__PlayerData_V[this] == -1
            // If the struct is a private struct from a library or a scope
            // it changes the variable's name...
            // Ex. : si__LibraryName___PlayerData_V
        endmethod
       
    endstruct


    It's worth using a separated boolean IMO.
     
  11. deathismyfriend

    deathismyfriend

    Joined:
    Oct 24, 2012
    Messages:
    6,526
    Resources:
    14
    Spells:
    12
    Tutorials:
    2
    Resources:
    14
    trilititi are u sure checking if this != 0 wont work ? if the only time it doesnt work is like this.
    Then you could always include in ur destroy method a set this = 0 just make sure to put it after the deallocate.
     
  12. Tirlititi

    Tirlititi

    Joined:
    Jul 11, 2010
    Messages:
    396
    Resources:
    12
    Models:
    6
    Maps:
    2
    Spells:
    3
    JASS:
    1
    Resources:
    12
    I'm sure that's not going to help :p
    "this" is an argument in the precompiled script. It is useless to null it (it won't be effective outside of the method, as PurgeandFire111 said (and I just see he also told about the variable though he didn't name it ^^)).
     
  13. deathismyfriend

    deathismyfriend

    Joined:
    Oct 24, 2012
    Messages:
    6,526
    Resources:
    14
    Spells:
    12
    Tutorials:
    2
    Resources:
    14
    hmm ill have to check more on this when i can i used something like this quite often
    Code (vJASS):

    if this != 0 then
        local thistype this = thistype.create()
    elseif
        //do other actions here
    endif

    and i never had it bug even when i did try to pass an already created or destroyed struct into it.
     
  14. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,429
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    @death: Well, my example was just an example. The real problems occur when you are dealing with multiple functions (when you don't know when the instance has been deallocated), or if you saved the integer in a hash (or something similar). The best route is to just use a boolean.
     
  15. deathismyfriend

    deathismyfriend

    Joined:
    Oct 24, 2012
    Messages:
    6,526
    Resources:
    14
    Spells:
    12
    Tutorials:
    2
    Resources:
    14
    so something like this wont work ?
    Code (vJASS):
    method destroy takes nothing returns nothing
                call this.deallocate()
                set this = 0
            endmethod

    I made a couple of methods like this. what ur saying is i should get rid of these ?
    Code (vJASS):
    method isStruct takes nothing returns boolean
                return not this != 0
            endmethod
     
  16. PurgeandFire

    PurgeandFire

    Code Moderator

    Joined:
    Nov 11, 2006
    Messages:
    7,429
    Resources:
    18
    Icons:
    1
    Spells:
    4
    Tutorials:
    9
    JASS:
    4
    Resources:
    18
    Yeah it won't work.

    For example, if you do:
    Code (vJASS):
    struct X
        method destroy takes nothing returns nothing
            call this.deallocate()
            set this = 0
        endmethod

        static method hi takes nothing returns nothing
            local thistype this = thistype.allocate()
            call this.destroy()
            call BJDebugMsg(I2S(this)) // it won't display 0
        endmethod
    endstruct


    It is partially because the way the structs are handled internally. It is all converted to regular JASS, and the instances are actually just integers. When you have methods, it is just like having
    function destroy takes integer this returns nothing
    . Therefore, you are passing the instance to the function, but not the variable itself. Thus, when you set "this" to 0, you aren't affecting the "this" in any source function.