Hosting and domain costs until October 2024 have been generously sponsored by dumptruck_ds. Thank you!

FTE MULTITHREADED

From Quake Wiki

Revision as of 10:12, 16 September 2018 by 192.168.4.142 (talk) (Created page with " float(optional float sleeptime) fork = #210; void(optional __variant ret) abort = #211; void(float sleeptime) sleep = #212; QC 'threads' are not simultaneous, and can neve...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
float(optional float sleeptime) fork = #210;
void(optional __variant ret) abort = #211;
void(float sleeptime) sleep = #212;

QC 'threads' are not simultaneous, and can never be due to rampant global abuse. Only a single execution context can run at a single time. As a result, the 'threads' in QC are really just saved state.

For instance, to spin up a periodic timer, you can write some code like the following:

   if (fork())
   {
       while (!wasfreed(self))
       {
           print("Still alive!\n");
           sleep(0.1); //beware of the half-second rule that allows for an entity to get reused half a second after it was freed.
       }
       abort();
   }

The fork call can be used to specify a delay before the new thread's first execution. The abort must normally be called - failure to do so can result in the function returning to its caller, which is likely to result in weirdness when a function is called once but returns twice... The abort function acts like a whole series of return statements, returning not only from the current function but also all the way up to the engine, its argument is the value that should be returned to the function and thus may have value even without using fork or sleep. Note that sleeping does not sleep the engine, only the QC context. By the time the thread wakes up, the engine will have forgotten why it was running and will no longer do anything with any return values. If you need an explicit return value, then use fork(delay);abort(foo); instead of sleep, at least for the first sleep in a sequence. Beware that if you are sleeping in a thread that you didn't fork off explicitly so that it could sleep, then you may trigger all sorts of race conditions in your caller.

Sleeping or forking will retain a copy of all locals, and its references to self and other, but other globals and entities can AND WILL change wile your code is sleeping. On the plus side each sleep resets any runaway loop counters, leaving you free to do expensive processing - just be sure that nothing else unexpectedly changes your stuff while you sleep.