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

[Solved] Specific Instance Allocation

Status
Not open for further replies.

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
Hello. I want to ask for a way to allocate a specific struct instance that would not conflict with the normal allocation/deallocation method. Basically it does similar to thistype(instance) but you know that would cause conflicts from this example.
JASS:
static method someMethod takes nothing returns nothing
    local thistype i = thistype(2) //returns instance 2 of thistype
    local thistype a = allocate() //allocates instance 1
    local thistype b = allocate() //allocates instance 2 - which I intend to be 3
endmethod

So I hope you got what I mean. Thanks for those who'll help =)
 
Level 13
Joined
Nov 7, 2014
Messages
571
This is just a slight variation of the "normal" allocation that jasshelper uses for structs:

JASS:
struct Foo extends array
    private static thistype head = 0
    private thistype next
    private boolean in_use
    private static integer instance_count = 0

    static method allocate takes nothing returns thistype
        local thistype this

        if head != 0 then
            set this = head
            set head = head.next
        else
            loop
                if instance_count >= 8190 then
                    debug call BJDebugMsg("unable to allocate an instance of thistype")
                    return 0
                endif

                set instance_count = instance_count + 1
                exitwhen not thistype(instance_count).in_use
            endloop

            set this = instance_count
        endif

        set this.in_use = true
        set this.next = -1
        return this
    endmethod

    static method allocate_specific takes integer i returns thistype
        set thistype(i).in_use = true
        return thistype(i)
    endmethod

    method deallocate takes nothing returns nothing
        if this == 0 then
            debug call BJDebugMsg("unable to deallocate a null instance of thistype")
            return
        elseif this.next != -1 then
            debug call BJDebugMsg("double free for instance of type thistype")
            return
        endif

        set this.in_use = false
        set this.next = head
        set head = this
    endmethod

    private static method onInit takes nothing returns nothing
        local thistype foo1 = allocate_specific(2)
        local thistype foo2 = allocate()
        local thistype foo3 = allocate()

        call BJDebugMsg(I2S(foo1))
        call BJDebugMsg(I2S(foo2))
        call BJDebugMsg(I2S(foo3))
        // =>
        // 2
        // 1
        // 3

        call foo3.deallocate()
        call foo3.deallocate()
    endmethod
endstruct
 

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
Actually I was expecting something like
JASS:
module SpecificAlloc
    private boolean allocated
    static method operator [] takes integer i returns thistype
        if not thistype(i).allocated then
            //Some stuffs here
            return i
        endif
        return 0
    endmethod
endmodule

But its okay, I think I haven't elaborated my question clearly.

What I'd like to do is a method for allocating a specific instance, a different one from the allocate() method and yet compatible with the usual allocate() and deallocate() methods. Although I get that for this to work, I have to write my own allocate() and deallocate() methods. What this method I was referring to does is just allocate a "specific" instance instead of just the next available instance as what allocate() does.
It's supposed to work like this.
JASS:
struct S extends array

    implement Alloc
    implement SpecificAlloc

    static method X takes nothing returns nothing
        local S a = S[3] // Allocates instance 3
        local S b = allocate() // Allocates instance 1
        local S c = allocate() // Allocates instance 2
        local S d = allocate() // Allocates instance 4 (because 3 was already specifically allocated)
        local S e = S[1] // returns 0 because thistype(1) was already allocated by the first allocate()
    endmethod

endstruct

EDIT:
Nevermind, I now see the whole text, my bad I didn't scroll =)

EDIT: I'm testing it
 
Last edited:

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
Tested and it works.
Btw
JASS:
    static method allocate_specific takes integer i returns thistype
        set thistype(i).in_use = true
        set thistype(i).next = -1 //this line is needed right?
        return thistype(i)
    endmethod

And also, is there a faster way to do this? Preferably without iterating through a loop and yet still be compatible for allocate_specific?
JASS:
        else
            loop
                if instance_count >= 8190 then
                    debug call BJDebugMsg("unable to allocate an instance of thistype")
                    return 0
                endif

                set instance_count = instance_count + 1
                exitwhen not thistype(instance_count).in_use
            endloop

            set this = instance_count
        endif
 
Last edited:
Level 13
Joined
Nov 7, 2014
Messages
571
set thistype(i).next = -1 //this line is needed right?
I guess it is, if instances that were obtained with the allocate_specific method are going to be destroyed and need the double free protection.

And also, is there a faster way to do this? Preferably without iterating through a loop and yet still be compatible for allocate_specific?
If you know the number of instances that need to be "specifically" allocated ahead of time you can just use the first X instances for them just by setting the initial value of instance_count to X, then you won't even need the in_use field, otherwise I don't know.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
Problem is that if allocate is called before allocate specific then allocate specific method may have to fail as the specific index has already been allocated by allocate. Allocating it again could cause state conflicts and violates contractual obligations of allocate.

Why do you need a specific constant index anyway? That kind of defeats the purpose of OOP. Maybe it would be better to dynamically allocate some static constant instances and then use those instead of a constant object identifier.
 

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
Problem is that if allocate is called before allocate specific then allocate specific method may have to fail as the specific index has already been allocated by allocate. Allocating it again could cause state conflicts and violates contractual obligations of allocate.
Its easy for me to add a check like
JASS:
    static method allocate_specific takes integer i returns thistype
        if not thistype(i).in_use then
            set thistype(i).in_use = true
            set thistype(i).next = -1
            return thistype(i)
        endif
        return 0
    endmethod

Why do you need a specific constant index anyway? That kind of defeats the purpose of OOP. Maybe it would be better to dynamically allocate some static constant instances and then use those instead of a constant object identifier.
Imagine a timer struct, like a vjass version of TimerUtils:
JASS:
private function A takes unit u returns nothing
    local Timer tempTimer = Timer.new()
    local Timer t = Timer[GetUnitUserData(u)] //where static method operator [] is a specific instance allocator
endfunction
So aside from Timer.new(), I think it would be useful to have Timer[instance] also.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
So aside from Timer.new(), I think it would be useful to have Timer[instance] also.
One might as well fake the array access then by adding a static array member to the type of Timer and then using that to map static index to Timer instances. This way it avoids messing with allocation at all while still allowing you do use that style of syntax. Might be slower but cannot ever fail like the suggested check can while still keeping the contractual obligations of allocate.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
In any case, you cant use both.
You cant use the specific instance allocation together with the normal allocation.
If you really want to, then you will have to redirect references if the instance is already in use, otherwise your old instance would have been destroyed.
And then you are better off just using that reference straight away.
So you would have a Timer array and you use the custom value of a unit as index.

If you only need the specific instance allocation, you dont need the allocation or the inUse fields.
You would just have to have a function that checks if the given index is already initialized.
 
Status
Not open for further replies.
Top