The engine can only choose to fire events (or do whatever else it has to do), when it is in controll. It is only in controll when your processor is executing instructions from the engine code, and not from your script. Your script is (implicitly) made to return to the engine code at several points (end of function, wait, engine functions).

So it is only at these times in your script, that the engine could possibly (!) choose to start another function (and an event is just a function). The engine doesn't check for events every time it is in controll (would be ridiculous if it fired events during a vec_set, for example), but it does in certain engine functions that can trigger events themselves, during wait and when a function is finished.

The way it checks for events is by looking at a queue of events to be processed. The networking thread (which DOES run in parallel to the script/engine) puts a new event on this queue when it receives a "update var" packet. The networking thread can't fire the event by itself, because then multiple functions would run in parallel, burdening the scripter with all the difficulties of concurent programming. If you know anything about concurent programming, you'll know this is not the case.

The way I see it, there is no way to program the engine to behave like you explained. On a low level, "events" don't exist. So they must somehow be fit into the inherently serial way a computer operates. When the scheduler starts a function, the scheduler is not running itself. So it can't possibly pause/abort/start another function, or set the value of a global var.