• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[Trigger] Memory leaks with "wait"

Status
Not open for further replies.
Level 1
Joined
Dec 8, 2010
Messages
2
Memory leaks with "wait" - Solved.

Hello there Hive, I hope you can help me with my simple question.

Now, in my map (which is 100% GUI as of now) there's lots of times where I find myself in a situation where a wait-command seems like a neccessity, e.g

  • For each (Integer A) from 1 to 18, do (Actions)
    • Schleifen - Aktionen
      • Set Karir_P2_Flammenspirale_Aim = (Karir_P2_Flammenspirale_Aim + 10.00)
      • Set Karir_P2_Flammenspirale_Aim_B = (Karir_P2_Flammenspirale_Aim_B + 10.00)
      • Einheit - Create 1 DUMMY - Schockwelle v. Flammenspirale for (Owner of Karir_P2_Flammenspirale_Caster) at ((Position of Karir_P2_Flammenspirale_Caster) offset by 200.00 towards Karir_P2_Flammenspirale_Aim degrees) facing Vorgabe für Gebäude-Ausrichtung degrees
      • Einheit - Add a 1.00 second Standard expiration timer to (Last created unit)
      • Einheit - Order (Last created unit) to Untoten-Schreckenslord - 'Aas-Schwarm' ((Position of Karir_P2_Flammenspirale_Caster) offset by 350.00 towards Karir_P2_Flammenspirale_Aim degrees)
      • Einheit - Create 1 DUMMY - Schockwelle v. Flammenspirale for (Owner of Karir_P2_Flammenspirale_Caster) at ((Position of Karir_P2_Flammenspirale_Caster) offset by 200.00 towards Karir_P2_Flammenspirale_Aim_B degrees) facing Vorgabe für Gebäude-Ausrichtung degrees
      • Einheit - Add a 1.00 second Standard expiration timer to (Last created unit)
      • Einheit - Order (Last created unit) to Untoten-Schreckenslord - 'Aas-Schwarm' ((Position of Karir_P2_Flammenspirale_Caster) offset by 350.00 towards Karir_P2_Flammenspirale_Aim_B degrees)
      • Wait 0.01 seconds
--Sorry for the Denglish, that's the German editor for you.--

A simple dummyspell (which works perfectly, mind you) that creates two Carrion-swarm type spells...Since I want it to look like a spiral, this has to have some sort of delay.

Now I know that the "wait" creates memoryleak of some sort. Is there any way to make this a little more elegant in GUI? I appreciate every bit of help. I can't really be bothered to learn JASS, so if that isn't really possible just tell me right away and I'll just stop, lol.

Thanks in advance :ogre_haosis:
 
Last edited:
Level 1
Joined
Dec 8, 2010
Messages
2
Alright, thanks a bunch. I always thought waits are heavy leaks...Oh well, TIL.

I'll do that then. Solved :thumbs_up:
 
Level 7
Joined
Jun 28, 2013
Messages
395
Wait function is not accurate. Even if you set it 0.01, it might take 0.3, idk but it isn't accurate.

Use Timer instead or if you dun want MUI (lol), you can use call TriggerSleepAction().. I just think this two are more accurate than that wait :p
 
Wait function is not accurate. Even if you set it 0.01, it might take 0.3, idk but it isn't accurate.

Use Timer instead or if you dun want MUI (lol), you can use call TriggerSleepAction().. I just think this two are more accurate than that wait :p

This is what the wait action / function does.
JASS:
function PolledWait takes real duration returns nothing
    local timer t
    local real  timeRemaining

    if (duration > 0) then
        set t = CreateTimer()
        call TimerStart(t, duration, false, null)
        loop
            set timeRemaining = TimerGetRemaining(t)
            exitwhen timeRemaining <= 0

            // If we have a bit of time left, skip past 10% of the remaining
            // duration instead of checking every interval, to minimize the
            // polling on long waits.
            if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) then
                call TriggerSleepAction(0.1 * timeRemaining)
            else
                call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
            endif
        endloop
        call DestroyTimer(t)
    endif
endfunction

TriggerSleepAction() is a wait. They are the same thing.

Yes timers / periodic triggers are much more efficient.

As said above though waits will never cause a leak.

Don't use WAITS! Forget this crap function!
Saying a statement like above is useless and rude.

@TO
Look at my tutorial Things you should know when using triggers / GUI for more info on waits. Also at the bottom of that there is a link for wait times and what the times actually are.
 
Level 7
Joined
Jun 28, 2013
Messages
395
This is what the wait action / function does.
JASS:
function PolledWait takes real duration returns nothing
    local timer t
    local real  timeRemaining

    if (duration > 0) then
        set t = CreateTimer()
        call TimerStart(t, duration, false, null)
        loop
            set timeRemaining = TimerGetRemaining(t)
            exitwhen timeRemaining <= 0

            // If we have a bit of time left, skip past 10% of the remaining
            // duration instead of checking every interval, to minimize the
            // polling on long waits.
            if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) then
                call TriggerSleepAction(0.1 * timeRemaining)
            else
                call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
            endif
        endloop
        call DestroyTimer(t)
    endif
endfunction

TriggerSleepAction() is a wait. They are the same thing.

Yes timers / periodic triggers are much more efficient.

As said above though waits will never cause a leak.

I see. Well, PolledWait script is longer than TriggerSleepAction?
 
Level 7
Joined
Jun 28, 2013
Messages
395
Polled wait is wait function of gui.. only it uses triggersleepactioc in it.. and have a ridiculously long script that can delay time
 
Level 7
Joined
Jun 28, 2013
Messages
395
I only used Wait-Game Time before.. What does Wait does? Timer still moves eventhough the game is pause?
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
I only used Wait-Game Time before.. What does Wait does? Timer still moves eventhough the game is pause?

Timers are paused when the game is paused, TriggerSleepAction is not.

But i'm not sure this will work :

JASS:
local integer i = 0
call PauseGame(true)
loop
    set i = i+1
    call TriggerSleepAction(1)
    call BJDebugMsg(I2S(i))
exitwhen i == 5
endloop
call PauseGame(false)

I mean maybe only "1" is displayed and the game never get unpaused.
 
Level 7
Joined
Jun 28, 2013
Messages
395
TriggerSleepAction still runs when game is pause... I see... Lewl.. Lemme test, I would like to see :p
 
Level 12
Joined
Feb 22, 2010
Messages
1,115
You guys are just mad because wait makes some things simpler and you don't like simple things.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
You guys are just mad because wait makes some things simpler and you don't like simple things.

Nope, i like simple things but hate more random innacurate things, and really that's pretty much the reason why i don't use PolledWait (but because the handle id leak i would use a custom PolledWait instead).

Now, the behavior of TSA is needed in particular cases (such as unpausing the game after X seconds)

Note that i'm stil curious about the test of the script above.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
I thought the main problem with Waits is player latency.
Of course making triggers with waits are harder to make MUI but still manageable.

Actually it's easier to make MUI with waits VS timers, but you can't really manage the innacuracy, that's random.
Now, some simple things don't need accuracy and the more longer is the wait, the most accurate it is. (innacuracy / duration of the wait)
 
Actually it's easier to make MUI with waits VS timers, but you can't really manage the innacuracy, that's random.
Now, some simple things don't need accuracy and the more longer is the wait, the most accurate it is. (innacuracy / duration of the wait)

Ah yes of course. I was referring to triggers without the need of timers/waits :)
Anyway.
 
Level 12
Joined
Feb 22, 2010
Messages
1,115
Ah yes of course. I was referring to triggers without the need of timers/waits :)
Anyway.

He is talking about jass triggers, they are easy to MUI with waits if you don't need high frequency(fast) timer periods.
 
Timers are paused when the game is paused, TriggerSleepAction is not.

But i'm not sure this will work :

JASS:
local integer i = 0
call PauseGame(true)
loop
    set i = i+1
    call TriggerSleepAction(1)
    call BJDebugMsg(I2S(i))
exitwhen i == 5
endloop
call PauseGame(false)

I mean maybe only "1" is displayed and the game never get unpaused.
It printed 1-5 correctly. Game was unpaused after these 5 seconds.
 
Level 7
Joined
Jun 28, 2013
Messages
395
You guys are just mad because wait makes some things simpler and you don't like simple things.
Wait is inaccurate and as they said, handle id leak.

So does this leak stack up each time PolledWait is called until the game goes overlag? If it does, another reason to not like it.. :/
 

Wrda

Spell Reviewer
Level 28
Joined
Nov 18, 2012
Messages
1,994
Wait is inaccurate and as they said, handle id leak.

So does this leak stack up each time PolledWait is called until the game goes overlag? If it does, another reason to not like it.. :/
So, stupidly, you would prefer to use a periodic timer to make a cinematic without those leaks and innaccuracy? Sorry but that seems pretty retarded. Yes, waits ignore the paused game, that's really so bad.
 
Level 7
Joined
Jun 28, 2013
Messages
395
^ I was asking a question if its leak would stack... What does it have to do with a cinematic? ==
 

Wrda

Spell Reviewer
Level 28
Joined
Nov 18, 2012
Messages
1,994
Of course it stacks, but it's not because of it that the game will lag. Two of things that can cause lag are the leak of locations and massive units on a determined area, especially it causes randomly an additional delay when you order a unit to do something etc.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,258
TriggerSleepAction is not inherently evil, it is just not that useful. Why use a grumpy old horse that is unreliable and hard to control when you can use a GPS controlled tractor that does more with less hassle?

PolledWait is inherently evil as a bug in how locals are destroyed results in a handle index leak every call. This is the other form of wait in GUI.

TriggerSleepAction has very bad delay precision. What is worse is that although the delay is deterministic inside a session, it is not between sessions so the same wait can produce a variety of results. Multiplayer always has longer delays than single player (Round Trip Time is probably involved somewhere and the reason for this). This makes robust use of TriggerSleepAction alone very difficult. It also means that it is not usable when small and precise delays are required. People report that it also does not account for the game being paused, another problem you need to factor in when using it robustly.

The idea behind polled wait is pretty good and not evil. A custom declaration of polled wait with proper timer nulling before the return (or that takes a re-usable timer as an argument) can help eliminate the inaccuracies of TriggerSleepAction over long periods and fix the game pause problem. It still does not make TriggerSleepAction viable for short delays, I would only recommend using it for delays >1 second where if it finishes in 1 or 1.3 seconds nothing bad happens.

Timers on the other hand do not suffer this accuracy problem and appear to have sub-frame precision. This makes them far more attractive than TriggerSleepAction for high precision tasks. The only problem with Timers is the way they are used is quite complicated and not good for scripting productivity.

It should be noted that cinematics are not designed to be paused as the gameplay is considered paused (user is stuck watching) and can be skipped to a pause-able state. Thus as long as the sequence of actions in the cinematic is strong enough to tolerate imprecise timing in the other of 10th of a second then TriggerSleepAction is perfect to use.
 
Level 5
Joined
Aug 8, 2008
Messages
113
Just like "do nothing" function :D so 'useful'

script where do nothing caused the script to work
In gui it actually caused my script to work when

I use alot of if then else statements

and

in the first if then else statement I had it "do nothing"

then I counted it going down backwards instead of forwards.

using an interger

ill post script here in a second
  • Phyiscal Ward
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Item Shockwave
    • Actions
      • Set point = (Target point of ability being cast)
      • Unit - Create 1 Dummy Caster for Player 1 (Red) at point facing (Position of (Triggering unit))
      • Set unit = (Last created unit)
      • Set point_target = (Position of unit)
      • Set point_Copy = (Position of (Triggering unit))
      • Wait until ((unit is alive) Equal to True), checking every 0.10 seconds
      • Unit - Create 1 Dummy Caster for Player 1 (Red) at point_Copy facing (Position of (Triggering unit))
      • Set unit_Copy = (Last created unit)
      • Set point_Caster = (Position of unit_Copy)
      • Unit - Add Sentry Ward to unit_Copy
      • Unit - Set level of Sentry Ward for unit_Copy to 1
      • Unit - Order unit to Orc Witch Doctor - Sentry Ward point_Caster
      • Wait until ((unit_Copy is alive) Equal to True), checking every 0.10 seconds
      • Set Amount_of_wards = (Amount_of_wards + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Amount_of_wards Equal to 0
        • Then - Actions
          • Do nothing
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Amount_of_wards Equal to 1
            • Then - Actions
              • Unit - Create 1 Dummy Face for Player 1 (Red) at point_Copy facing point_target
              • Set Face = (Facing of (Last created unit))
              • Unit - Order unit to Orc Witch Doctor - Sentry Ward point_Caster
              • Set Loc_1_Forward = (point_Caster offset by -700.00 towards Face degrees)
              • Set Loc_1_Behind = (point_target offset by 700.00 towards Face degrees)
              • Unit - Create 1 Dummy Caster for Player 1 (Red) at Loc_1_Forward facing (Position of (Triggering unit))
              • Unit - Create 1 Dummy Caster for Player 1 (Red) at Loc_1_Behind facing (Position of (Triggering unit))
              • Set unit_3 = (Last created unit)
              • Wait until ((unit_3 is alive) Equal to True), checking every 0.10 seconds
              • Unit - Add Sentry Ward to unit_3
              • Unit - Set level of Sentry Ward for unit_3 to 1
              • Unit - Order unit_3 to Orc Witch Doctor - Sentry Ward Loc_1_Behind
              • Wait until (((Last created unit) is Summoned) Equal to True), checking every 0.10 seconds
              • Set scout = (Summoned unit)
              • Wait until ((scout is alive) Equal to True), checking every 0.10 seconds
              • Unit Group - Add scout to Group
              • Game - Display to (All players) for 5.00 seconds the text: Successful Trigger
              • Custom script: call RemoveLocation (udg_point_Copy)
              • Custom script: call RemoveLocation (udg_point)
              • Custom script: call RemoveLocation (udg_point_target)
              • Custom script: call RemoveLocation (udg_point_Caster)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Amount_of_wards Equal to 2
                • Then - Actions
                  • Set Amount_of_wards = (Amount_of_wards - 1)
                • Else - Actions
                  • Do nothing
  • Ward Move
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • steps Greater than or equal to 0
          • steps Less than or equal to 99
        • Then - Actions
          • For each (Integer steps) from 1 to 99, do (Actions)
            • Loop - Actions
              • Unit - Move scout instantly to (Loc_1_Forward offset by 25.00 towards Face degrees)
              • Wait 1.00 game-time seconds
              • Set steps = (steps + 1)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • steps Greater than or equal to 100
              • steps Less than or equal to 199
            • Then - Actions
              • Unit - Move scout instantly to (Loc_1_Behind offset by -25.00 towards Face degrees)
              • Wait 1.00 game-time seconds
              • Set steps = (steps + 1)
            • Else - Actions
              • Do nothing
  • Ward Para
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • If (steps Greater than or equal to 199) then do (Set steps = 0) else do (Do nothing)
note
there are other scripts for this code but it still works. what it does is its suppose to create an owl that travels back and forth and function as a mobile ward. Kobas recoded in jass to be more efficient becuase it wasn't mui and it required alot of code so you could have it mui and be able to place alot of wards also.
 
Status
Not open for further replies.
Top