HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Trigger recycler

10-02-2007, 01:59 AM#1
moyack
Hi guys:

After one discussion taken in this section about vJASS (I forgot where and when was this, probably everywhere :P), the fact is that it was mentioned the command ResetTrigger(t). After that, it started to buzz in my head the idea, if we can recycle timers, why not recycle triggers too??

Then I did a small modification of CSSafety and using the beautiful vJASS I wrote this code:
Hidden information:

Collapse CSSafety 2.0 LOL!!:
//******************************************************************************************
//*
//* CSSafety with trigger support
//* ¯¯¯¯¯¯¯¯ ¯¯¯¯ ¯¯¯¯¯¯¯ ¯¯¯¯¯¯¯
//* Based on CSSafety by Vexorian.
//*
//* Utilities to make things safer. Currently this simply includes a timer and trigger 
//* recycling Stack.
//* 
//* Usage:
//*        Timers:   Replace CreateTimer()  by NewTimer()
//*                  Replace DestroyTimer() by ReleaseTimer()
//*
//*        Triggers: Replace CreateTrigger()  by NewTrigger()
//*                  Replace DestroyTrigger() by ReleaseTrigger()
//*
//* Once you replace those commands, you no longer have to care about setting them to null 
//* nor problems with handles stack.
//*
//******************************************************************************************
library CSSafety

private function DebugText takes string s returns nothing
debug call DisplayTimedTextFromPlayer(Player(0), 0,0,5, s)
endfunction 

//! textmacro CSStructs takes OBJECT, FUNCNAME, CREATEOBJ, RECYCLEOBJ
globals
    private $OBJECT$ array $OBJECT$s
    private integer $OBJECT$n = 0
endglobals

function New$FUNCNAME$ takes nothing returns $OBJECT$
    if ($OBJECT$n==0) then
        debug call DebugText("New $OBJECT$...")
        return $CREATEOBJ$()
    endif
    set $OBJECT$n = $OBJECT$n - 1
    debug call DebugText("Using recycled $OBJECT$ with index " + I2S($OBJECT$n))
    return $OBJECT$s[$OBJECT$n]
endfunction

function Release$FUNCNAME$ takes $OBJECT$ t returns nothing
    call $RECYCLEOBJ$(t)
    if ($OBJECT$n == 8191) then
        debug call DebugText("Warning: $FUNCNAME$ stack is full, destroying $OBJECT$!!")

        //stack is full, the map already has much more troubles than the chance of bug
        call Destroy$FUNCNAME$(t)
    else
        debug call DebugText("Recycled $OBJECT$ with index " + I2S($OBJECT$n))
        set $OBJECT$s[$OBJECT$n] = t
        set $OBJECT$n = $OBJECT$n + 1
    endif    
endfunction
//! endtextmacro

//! runtextmacro CSStructs("timer", "Timer", "CreateTimer", "PauseTimer")
//! runtextmacro CSStructs("trigger", "Trigger", "CreateTrigger", "ResetTrigger")
endlibrary


I did it in that way because I wanted to do a quick test about how it behaves. I did a test map where I add to each unit created an event damage trigger, that makes explode the unit when it receives the attack.

Due that I'm not good at benchmarking, I'd like to know if this test can be done in a better way (I'm sure there is a better way). Please feel free to edit the map in order to improve the benchmark, and of course, any bugs or improvements to this library are welcome.

This is the code of the testing test map:
Hidden information:
Collapse JASS:
library hardfight requires CSSafety, HandleVars

private function Damage takes nothing returns nothing
    local unit u = GetTriggerUnit()
    call KillUnit(u)
    call ReleaseTrigger(GetTriggeringTrigger())
    set u = null
endfunction

public function Actions takes nothing returns nothing
    local real y = GetRandomReal(-600., 600.)
    local unit u1 = CreateUnit(Player(1), 'nchg', -2500., 0., 0.)
    local unit u2 = CreateUnit(Player(2), 'nchg', 2500., 0., 180.)
    local trigger t
    
    call SetUnitPathing(u1, false)
    call SetUnitExploded(u1, true)
    call SetUnitPathing(u2, false)
    call SetUnitExploded(u2, true)
    
    set t = NewTrigger()
    call TriggerRegisterUnitEvent( t, u1, EVENT_UNIT_DAMAGED )
    call TriggerAddAction( t, function Damage )
    
    set t = NewTrigger()
    call TriggerRegisterUnitEvent( t, u2, EVENT_UNIT_DAMAGED )
    call TriggerAddAction( t, function Damage )
    
    call IssuePointOrder(u1, "attack", 0., y)
    call IssuePointOrder(u2, "attack", 0., y)
    
    set u1 = null
    set u2 = null
    set t = null
endfunction

endlibrary

//===========================================================================
function InitTrig_Put_hard_fight takes nothing returns nothing
    set gg_trg_Put_hard_fight = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Put_hard_fight, 0.1 )
    call TriggerAddAction( gg_trg_Put_hard_fight, function hardfight_Actions )
endfunction

Attached Files
File type: w3xDynamicTriggers.w3x (14.4 KB)
10-02-2007, 03:02 AM#2
Pyrogasm
What about those nasty things called TriggerActions? Won't you be leaking those, as the handle will still exist when you call ResetTrigger()?

Or does ResetTrigger destroy a trigger's TriggerActions?
10-02-2007, 03:07 AM#3
Blackroot
I beileive ResetTrigger is a combination of:

Code:
native TriggerClearActions takes trigger whichTrigger returns nothing
native TriggerClearConditions takes trigger whichTrigger returns nothing

I think it cleans registered events, too. Don't quote me on that, though.
10-02-2007, 03:16 AM#4
moyack
Quote:
Originally Posted by Pyrogasm
What about those nasty things called TriggerActions? Won't you be leaking those, as the handle will still exist when you call ResetTrigger()?

Or does ResetTrigger destroy a trigger's TriggerActions?

As I've seen, ResetTrigger function cleans the conditions and actions, but probably I'm wrong, in fact, that's one of the reason why I posted the code.
10-02-2007, 03:20 AM#5
Vexorian
I swear I tested ResetTrigger and it does not remove events, at least it won't prevent any memory use from their part.

The deal is that, as a matter of fact, we don't really need dynamic triggers, would ellaborate if I wasn't about to sleep.
10-02-2007, 03:23 AM#6
Pyrogasm
It clears them, sure. But what does that mean? Aside from removing them from the trigger, what happens to them? In fact, I'm not even sure that TriggerRemoveAction even destroys the TriggerAction.
10-02-2007, 07:15 AM#7
cohadar
Well in my little OnDamage thingy I create and destroy damage trigger for every unit, it does not seem to make any lag so there you go...
10-02-2007, 07:27 AM#8
Toadcop
Quote:
I swear I tested ResetTrigger and it does not remove events, at least it won't prevent any memory use from their part.

The deal is that, as a matter of fact, we don't really need dynamic triggers, would ellaborate if I wasn't about to sleep.
me 2 =\ i mean it doesnt remove events... it resets eval/exec count of the trigger. but recylable triggers would be cool ! (i wanted to create it long ago...)
10-02-2007, 07:34 AM#9
cohadar
Well all you need is a RemoveEventFromTrigger() function...
But I guess there is none.

I wonder what will Vexorian "elaborate"
10-02-2007, 02:56 PM#10
blu_da_noob
ResetTrigger doesn't remove events. TriggerClearActions 'removes' the actions from the trigger but doesn't actually remove the actions (I tested clear actions vs remove actions and clear actions caused a constant memory increase while remove did not). I can't speak for clear conditions.
10-02-2007, 07:23 PM#11
Pyrogasm
ConditionFuncs don't leak, as far as I know. Vexorian posted a thread about it called "Triggers and Conditions and Stuff", I believe.
10-02-2007, 07:55 PM#12
Toadcop
they are destroyed together with the trigger like the events.
(so works only on DestroyTrigger())

ohhh ! ^^ my 777 post xD *party*
10-03-2007, 02:04 AM#13
moyack
Thanks for the comments, now I have one question for you guys:

How can we do a good benchmark for the trigger recycler that I did?? Any suggestions?? or, as Vex said, we don't really need dynamic triggers, and this code is only useful with timers??
10-03-2007, 06:51 AM#14
Pyrogasm
I'd say that it's completely useless with triggers.
10-03-2007, 08:11 AM#15
Toadcop
but it doesnt work properly =) (or O_O)