Snippet Recycle

quraji

zap
Reaction score
144
I actually really like this Nesth, it's not over the top like your usual stuff :D
I really like the idea of using struct array and getting the struct syntax. Good stuff :thup:

JASS:
private static integer $type$Index = 0


You don't need the $type$.

That's the best critique you can come up with? :p
 

Jesus4Lyf

Good Idea™
Reaction score
397
Excuse what I said before in my 1 am post. For timers, this is under no circumstances faster than TU.

>This is the same thing as mine o_O
You recycle texttags and put debug messages for recycling too many things in your "get" function. :confused:
Which I've told you in your thread, but you haven't updated the resource.

Anyway, approved. This seems perfect to me.
But yes, remove the $type$ from before Index in the struct macro - may as well. :)

:thup:
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
JASS:
Actually i suspect GetHandleId is the only one return bug allowed, i mean when the script is compiled, it basically convert GetHandleId to the return bug.


I benchmarked GetHandleId is faster than H2I by 30% (on 1.24)
 

Nestharus

o-o
Reaction score
84
Ok, so how would people like this for an update?

This changes to C syntax instead of C# syntax ^_^. I can keep it at C# syntax, but at the least I want to get that struct out of there : o.

In other words-
C- get timer()
C#- Timer.get()

C- release timer(timer t)
C#- Timer.release(timer t)

JASS:
/*Utility Information
//===================================================================
Name: Recycle
Version: 4.0
Author: Nestharus
-Help from Jesus4Lyf for initial designs

Description:
    What does it do-
        A stack of a type. When you are done using something, 
        you throw it into the stack and it is added to the stack. 
        When you need something, it'll either get something from the 
        stack, or it'll create new if the stack is empty. This is very 
        simple, but I keep having to rewrite this over and over again 
        so I figured this'd be cooler : ).
        
Requirements: NA

Installation: NA

Functions:
------------------------------------------------------------------
-get returns type
    will return the type
    
    timer t = get timer();
    group g = get group();
    hashtable h = get hashtable();
    

-release(type h)
    Will release the type and stop it.
    
    release timer(timer h);
    release group(group h);
    release hashtable(hashtable h);
------------------------------------------------------------------*/
library Recycle
{
    define
    {
        <release timer(> = Recycle_HandleSSStimer_release(
        <get timer(> = Recycle_HandleSSStimer_get(
        
        <release group(> = Recycle_HandleSSSgroup_release(
        <get group(> = Recycle_HandleSSSgroup_get(
        
        <release hashtable(> = Recycle_HandleSSShashtable_release(
        <get hashtable(> = Recycle_HandleSSShashtable_get(
    }
    //! textmacro CREATE_STACK takes type, clean, create
        scope HandleSSS$type$
            private $type$ array handles;
            private int index = 0;
            
            public void release($type$ h)
            {
                debug if (h == null)
                debug {
                    debug print("ERROR - Recycle: Freed null handle.");
                debug }
                debug if (index > 8191)
                debug {
                    debug print("ERROR - Recycle: Overfilled recycle stack (8191 released objects)!");
                debug }
                $clean$
                handles[index] = h;
                index++;
            }
            
            public $type$ get()
            {
                if (index == 0)
                {
                    return $create$;
                }
                index--;
                return handles[index];
            }
        endscope
    //! endtextmacro
    
    //! runtextmacro CREATE_STACK("timer", "PauseTimer(h);", "CreateTimer();")
    //! runtextmacro CREATE_STACK("group", "GroupClear(h);", "CreateGroup();")
    //! runtextmacro CREATE_STACK("hashtable", "FlushParentHashtable(h);", "InitHashtable();")
}
 

Jesus4Lyf

Good Idea™
Reaction score
397
>so how would people like this for an update?
I would graveyard it on sight.

You don't seem to understand what it means to have a resource like this approved. The only thing that is important is keeping the interface exactly the same, with the same compatabilities and not making it suck, ever.

Do you realise people are already using this resource, including myself?
 

Nestharus

o-o
Reaction score
84
Ok, I have an idea then : ).

So, let's say we have the cJASS thing, but I put in both C# and C syntax, meaning that people currently using this will have their stuff still work and new users can use whatever syntax they feel like : ). Some people like the C# Syntax and some people like the C Syntax =P. So, how about just having ^_^.
 

Nestharus

o-o
Reaction score
84
Ok, then, let's say this-

This will only be changed to the possible 4.0 version when and if the helper accepts cJASS ^_^. If the helper never accepts cjass, current one stays for sure ^_^.

What this would mean if the helper accepted cjass and the update took place

1. It'd be pretty much the exact same.
2. The speed would be the same.
3. Resources using it right now would still work with the update as the current syntax wold still be there.
4. People could choose between C syntax and C# syntax.

How does that sound?
 

Van Damm

New Member
Reaction score
7
Your cJass code will not compile cause you didn't include "cj_types_priv", and it's at the same time not cJass-way, you should use defines whenever you can:
JASS:
library Recycle
{
    include "cj_types_priv.j" // you forgot this - it's needed for void, int etc

    define
    {
        <release timer>(h) = Recycle_HandleSSStimer_release(h)
        <Timer.release>(h) = Recycle_HandleSSStimer_release(h)
        <get timer()> = Recycle_HandleSSStimer_get()
        <Timer.get()> = Recycle_HandleSSStimer_get()

        <release group>(h) = Recycle_HandleSSSgroup_release(h)
        <Group.release>(h) = Recycle_HandleSSSgroup_release(h)
        <get group()> = Recycle_HandleSSSgroup_get()
        <Group.get()> = Recycle_HandleSSSgroup_get()

        <release hashtable>(h) = Recycle_HandleSSShashtable_release(h)
        <Hashtable.release>(h) = Recycle_HandleSSShashtable_release(h)
        <get hashtable()> = Recycle_HandleSSShashtable_get()
        <Hashtable.get()> = Recycle_HandleSSShashtable_get()

        CREATE_STACK(type, clean, create) =
        {
            scope HandleSSS##type
            {
                private type array handles
                private int array data
                private int index = 0

                public void release(type h)
                {
                    debug if (h == null){ print("ERROR - Recycle: Freed null handle.") }
                    debug if (index > 8191) { print("ERROR - Recycle: Overfilled recycle stack (8191 released objects)!") }
                    clean
                    handles[index++] = h
                }

                public type get()
                {
                    if (index == 0)
                    {
                        return create
                    }
                    return handles[--index]
                }
            }
        }

        CREATE_STACK(timer, PauseTimer(h), CreateTimer())
        CREATE_STACK(group, GroupClear(h), CreateGroup())
        CREATE_STACK(hashtable, FlushParentHashtable(h), InitHashtable())
    }
}
 

Kenny

Back for now.
Reaction score
202
Quick (and probably stupid question):

In your get method, it looks as if you are just creating a timer/group and not allocating it to the struct. Am I seeing things correctly?

If that is true, does that mean you just wait for a timer/group to be released and add it as a struct member upon release?

I thought something like this would be better (but then again I don't know how it would go with structs, I'm very rusty):

JASS:
public static method get takes nothing returns $type$
    if $name$.index == 0 then
        set $name$[0].handles = $create$
    else
        set $name$.index = $name$.index - 1
    endif

    return $name$[$name$.index].handles
endmethod


I'm pretty sure that the $name$[0] thing wouldn't work, as 0 is used as a null struct, but there would be some work around right? Or have I just got everything mixed up?
 

Azlier

Old World Ghost
Reaction score
461
I don't see why it wouldn't work. If you release a handle, it goes into the stack and index goes up. When you get a handle, it gets one of the in the stack. If index is 0 (no more handles in the stack), create a new handle. Struct slot 0 can be used for whatever the user desires without much problem. I don't see it...
 

Kenny

Back for now.
Reaction score
202
Yeah I realised that much. I read over struct arrays when AIDS came out. So you are saying the method I posted would still work?

Also, wouldn't this be a little better for the release method:

JASS:
public static method release takes $type$ h returns nothing
    if h == null then
        debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "ERROR - Recycle: Attempt to free null handle.")
        return
        // Seems more logical to me to report the attempted freeing of a handle, rather than just letting it happen.
    endif

    if $name$.index == 8191 then // Changed from > to ==
         debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "ERROR - Recycle: Stack full, destroying a handle.")
         call DestroyTimer(h) // DestroyGroup(h)
         // Added safety if the stack ever does get full. You have more to worry about than destroying a timer or group if this occurs.
    else
        $clean$
        set $name$[$name$.index].handles = h
        set $name$.index = $name$.index + 1
    endif
endmethod
 

Nestharus

o-o
Reaction score
84
debug if h == null then
debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "ERROR - Recycle: Attempt to free null handle.")
return
// Seems more logical to me to report the attempted freeing of a handle, rather than just letting it happen.
endif

That portion is going to stay in debug. This is made to be as efficient and as fast as possible, meaning it will have 0 safety checks when not in debug mode =). In debug mode, it really doesn't matter what it does, so it's just a waste of a line to keep it safe.

if $name$.index == 8191 then // Changed from > to ==
debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "ERROR - Recycle: Stack full, destroying a handle.")
call DestroyTimer(h) // DestroyGroup(h)
// Added safety if the stack ever does get full. You have more to worry about than destroying a timer or group if this occurs.
else

Same case here. This portion is going to stay in debug, and when in debug mode it doesn't really matter what it does. Safety is never going to be added to this as it would slow it down. In fact, this will become fully inlined when cJASS gets accepted ^_^. The inlining would increase the speed of this massively =).

$name$.index == 8191

That there is a valid point =), but that still isn't correct. It should be-
[ljass]$name$.index > 8190[/ljass]

Thanks for your feedback kenny, and thanks for finding the mistake =).

The next build will feature the fix, and the next version (whenever that day will be ><) will be cJASS to increase performance via inlining : D.

Edit:
4.1 up ^_^
 

Jesus4Lyf

Good Idea™
Reaction score
397
>Seems more logical to me to report the attempted freeing of a handle, rather than just letting it happen.

It is an efficiency perk. Basically since your code should never free a null handle, it should be reported in debug mode, and never find its way into a public version. Since the system must perform the same in debug mode and non-debug mode (on principle) this is the way it is written. So if the warning displays, you fix your code.

Same goes for the 8191 releases, really. Good luck releasing 8000 handles of one type, in general I'd expect maps to max at around 30. :thup:

If people think it really worth while, I'd opt that Nestharus release a safety version. Although I find it kinda retarded, personally.

>So you are saying the method I posted would still work?
All you're doing it storing it in the 0 slot for some reason before returning it, right? Lol...
 

Kenny

Back for now.
Reaction score
202
I see, thanks for the explanations guys. :)

This is a really handy snippet. I'll be using it for sure.

By the way, do you think there is a point to adding a trigger stack? Just wondering, I personally don't see a point to it. I was just wondering what your reasoning behind it was.
 

Nestharus

o-o
Reaction score
84
You can't reset events

If you didn't use events on a trigger and only used them as a means of evaluating a set of functions, then it would be useful to have a trigger stack, but as triggers can have events on them and those events cannot be removed, trigger stacks would be undependable.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top