• 🏆 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] Is Struct Instance Allocated

Status
Not open for further replies.
Level 5
Joined
Mar 22, 2009
Messages
170
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.
JASS:
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:
Level 37
Joined
Mar 6, 2006
Messages
9,240
You could add a boolean struct member, and set it to true when allocating the instance. Set it to false when deallocation

JASS:
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
 
Level 5
Joined
Mar 22, 2009
Messages
170
@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,
JASS:
        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.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
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
JASS:
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.
JASS:
    method isStruct takes nothing returns boolean
        return this != 0
    endmethod
if this doesnt equal 0 then it is a struct
 
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).
 
It might not always work. Consider this case:
JASS:
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.

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.

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. :)
 
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 :
JASS:
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.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
trilititi are u sure checking if this != 0 wont work ? if the only time it doesnt work is like this.
It might not always work. Consider this case:
JASS:
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

Then you could always include in ur destroy method a set this = 0 just make sure to put it after the deallocate.
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
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 ^^)).

hmm ill have to check more on this when i can i used something like this quite often
JASS:
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.
 
Yeah it won't work.

For example, if you do:
JASS:
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.
 
Status
Not open for further replies.
Top