• 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.

Temp Var

Status
Not open for further replies.
Level 8
Joined
Oct 2, 2013
Messages
288
When using TempVar (like points), are there absolutely no chance for them to conflict with each other? (As long as the trigger is an instant process - no waiting functions)

I understand it's impossible for spells that uses TempPoints to conflict with each other since spells can never be cast the same instant (at least as far as I understand).

But what about Timer Events that may pop at the same time?

Is there anything I should be aware of?
 
Level 5
Joined
May 6, 2013
Messages
125
Watch out. Its not about the waits, its about the interruptions. e.g. killing a unit will execute all "a unit dies" triggers before continuing, issuing an order will execute order issue triggers etc. If such a trigger uses the same variable, it will conflict without a single wait.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
Watch out. Its not about the waits, its about the interruptions. e.g. killing a unit will execute all "a unit dies" triggers before continuing, issuing an order will execute order issue triggers etc. If such a trigger uses the same variable, it will conflict without a single wait.
If you understand the mechanics this way, you're gonna have a bad time.

All process/thread occurs instantly and they will never collide with each other if and only if the process occurs without delay (Wait, Timer, Interval, etc).

So if you have like 50 triggers, all using the same variable and occurs "simultaneously", it still works.

Because the process never is "simultaneously", it has its queue - which can't be seen by human's eye (frame rate).

If you have 3 different triggers, using same variable, the process queue would be from Top to Bottom, meaning that the top-most trigger would be fired first, followed by middle trigger, lastly the bottom-most trigger.

If you want to experiment this and see for yourselves, follow these triggers;

  • A
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • Game - Display to (All players) the text: A
  • B
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • Game - Display to (All players) the text: B
  • C
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • Game - Display to (All players) the text: C
Align all these triggers in the following order: A B C

When you press ESC button, you notice the debug message would be:
A
B
C

This shows that the process queue works from Top to Bottom order.
 
Level 5
Joined
May 6, 2013
Messages
125
@defskull: you pretty much missed my point. I'm well aware of how the trigger execution works. And in case you actually understood what i was saying but actually thought it was wrong, here is something to learn for you:

  • T1
    • Events
      • Player - Spieler 1 (Rot) types a chat message containing -test as Exakte Ãœbereinstimmung
    • Conditions
    • Actions
      • Set temp = 1
      • Unit - Kill Priester 0000 <gen>
      • Game - Display to (All players) the text: (String(temp))
  • T2
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Set temp = 2
This is what im talking about.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
If such a trigger uses the same variable, it will conflict without a single wait.
This statement shows that even if you use same variable, you will have data collision with or without wait.

In programming, we are advised to use as many same variable as we can IF the instance does not occur simultaneously at any given time.

In your previous post, the trigger does exactly what it should do, Use same variable for different purpose - this way we will save the space for other variable.

You don't want to keep using different variable unit for instant unit-assign would you ?
You should always stick to TempUnit, instead of PickedUnit_WE, PickedUnitWF, etc - WE and WF is acronym of example name of spells.
 
Level 5
Joined
May 6, 2013
Messages
125
I actually hold the opinion that you can learn things best by doing them, and the triggers given were an example of data collision occurring without waits, hoping that you would test it yourself and see it. However, as you seemingly didn't do it, i'm gonna give an explanation anyway:

Of course, in essence, triggers are processed sequentially. The message queues head is poped and the resulting message processed by invoking every trigger that registered itself to react on said message in a certain order (the order in which they registered, i guess). Data collision of global variables occurs when a global is modified by a trigger in a certain point of execution where a other trigger does not expect the value to be changed and therefor continues to use a now invalid value. A wait function can cause such collision because it suspends the pseudo-thread executing the trigger and allowing others to execute, which may change the variable.
However, waits are not the only thing that might invoke other triggers within the execution of a trigger. For example, Syncing operations typically involve a "hidden wait" while waiting for answers of the other players and will therefor have similar problems. And the other way of interrupting a trigger is what i pointed out:
when you call a native function that creates a new message (such as the KillUnit native that creates a "a unit died" message, or the "issue order" native that creates a "a unit has been issued an order" message), this message is immediately processed (whether or not it is actually posted to the message queue in a SendMessage-fashion, i can't tell, as i never hacked and looked into that part of the game), and as we know, processing a message means invoking every trigger that registered itself to react to that message. And this processing is blocking; the native does not return until the message has been evaluated and dispatched.
In the example given above, i had a trigger that fires on the "a unit dies" event. When T1 fires, it sets its temp global variable to 1 and kills a unit; the KillUnit native invokes T2 which writes a 2 into temp. It then returns to the execution of T1 and causes it to show the value of temp to the player, which at this point is 2.
This is a common mistake, because as your map is growing and getting more systems reacting to stuff like aquires an item, dies, issued an order, enters a region (at move unit natives) etc etc, the amount of triggers executed inbetween can get quite huge, potentially scrambling pretty much every temporary global variable, including things like Integer A and Last Created Unit. It becomes virtually impossible to keep an overview over which temporary variable is still valid after creating a unit, killing a dummy or giving an item to a hero.
This is a little to non-existent problem in JASS, as common use of local variables circumvents this problem. However, for GUI systems, the consequence is that using the same temporary variables for systems and spells will eventually cause hard to find bugs, especially since you can not ask for help from anybody without giving the whole map, as every trigger with a suiting event could be the cause. The naive view of yours will not help you in the long run, and i do not advice anybody to be so thoughtless. When you plan on using temporary global variables, make sure you know about your triggers and which actions might scramble their values. Use (shadowed) locals as often as you can instead.
I am not against temporary variables in general. Of course they are a must have for many things, such as ForGroup actions and to get shadowed locals into if-blocks. But be extremely cautious when using them, because it is NOT that easy as it seems.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Basically you should share variables as much as you can between your triggers.

No. That would destroy modularity, make it unreadable and interrupt-precarious as Imp Midna explained. Variables are primitive assets and cheap.

I am not against temporary variables in general. Of course they are a must have for many things, such as ForGroup actions

There are ways to alienate the value passing, so you can write it that way:

JASS:
function enum takes nothing returns nothing
    local datatype data = GetEnumData()
endfunction

call ForGroupEx(g, function enum, data)
 
Status
Not open for further replies.
Top