Starfield Mod:Papyrus-Guards
Guards provide a new form of concurrency management that allow you to acquire locks for blocks of code, functions, properties and variables
Guards provide for threadsafety.
The Papyrus runtime is highly parallelized, and multi-threaded in ways mostly opaque to the developer. That is, without trying your script is already capable of multithreading, but not threadsafe. Most external and native calls unlock the scriptobject -- even nowaits may. Basically if there is any chance your thread may need to wait on another object, your thread is paused and placed at the end of the line with any other waiting threads. There has been a longstanding problem when you needed to "synchronize" threads. Guards aim to solve the problem.
Guard Definition:
;Declares a data guard, that must be used with a corresponding RequiresGuard() on a variable or property Guard guardName ;protects data ;Declares a guard that is used to protect a block of code Guard logicGuardName ProtectsFunctionLogic ...TODO
Usage examples
; declare the counter variable that requires single-threaded access int globalCounter = 0 RequiresGuard(counterGuard) ; Declare the guard Guard counterGuard ;... Function DoSomething() ; LockGuard <guardName> waits until it can obtain an exclusive lock on guardName (TODO: determine delay caused when the guard is free / overhead) ; and defines a code block closed with 'EndLockGuard' LockGuard counterGuard ; The VM must pause the thread to wait for the external call ; globalCounter's value could have changed, and will get set to the wrong value (race condition) ; Using LockGuard still allows the object to be unlocked, and other threads that don't alter the counter can run freely ; But no threads can get pasts this LockGuard, on this ScriptObject instance until it is free globalCounter += CallExternalFunction() EndLockGuard EndFunction ;TODO RequiresGuard on properties (full / auto), and functions TryLockGuard GuardName ;code ElseTryLockGuard GuardName2 ;code EndTryLockGuard