Starfield Mod:Papyrus-Guards

From Starfield Wiki
Jump to: navigation, search

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