-
Notifications
You must be signed in to change notification settings - Fork 0
Promise System
ffredyk edited this page Jul 23, 2026
·
1 revision
Every ScriptHandle in SQ# is a promise — an async operation that will complete with a value. Built on .NET Task<SqValue> under the hood.
When you spawn code, you get a ScriptHandle:
_handle = spawn { sleep 2; return 42; };
// _handle is a promise that will resolve with 42The handle tracks:
- Status: running or resolved
- Result: the return value (nil if none)
- Error: if the fiber threw an uncaught exception
scriptDone _handle; // true if resolved
isNull _handle; // same (SQF compat)_result = await _handle; // suspend until resolved, return valueterminate _handle; // force-resolve immediately_race = _handle timeout 5; // race against 5 seconds
_result = await _race;
if (isNil "_result") then {
terminate _handle; // timeout — cancel original
};await suspends the current fiber until the handle resolves. Returns the handle's result value:
_handle = spawn { sleep 1; return "done"; };
_result = await _handle; // "done"
// Already-resolved handles return immediately:
_handle2 = spawn { 1 + 2; }; // might complete instantly
_result2 = await _handle2; // returns 3 immediately (no suspension)Important: Only works in scheduled (spawned) code. Use
canSuspendto guard.
Races a handle against a timer. Returns a new handle:
_handle = spawn { sleep 10; return "slow"; };
_race = _handle timeout 3;
_result = await _race;
// If original completes within 3s → _result = "slow"
// If 3s passes first → _result = nil (original still running)The original handle is not automatically terminated. Use terminate if needed:
if (isNil "_result") then { terminate _handle; };Force-resolves a handle. The associated fiber stops immediately — no cleanup runs:
_handle = spawn { infiniteLoop(); };
terminate _handle; // stops the fiber
// Already-resolved handles are unaffected:
terminate _handle; // no-opAdvanced patterns for coordinating multiple async operations.
_handles = [
spawn { sleep 1; return "a"; },
spawn { sleep 2; return "b"; },
spawn { sleep 3; return "c"; }
];
_results = PromiseAll _handles; // ["a", "b", "c"]
// Resolves when ALL handles complete_handles = [
spawn { sleep 2; return "slow"; },
spawn { sleep 0.5; return "fast"; }
];
_winner = PromiseRace _handles; // "fast"
// Resolves with the FIRST handle to complete_handles = [
spawn { sleep 1; throw "fail"; },
spawn { sleep 2; return "ok"; }
];
_result = PromiseAny _handles; // "ok"
// Resolves with the first handle that succeeds (doesn't throw)_handle = spawn {
throw "Something broke";
};
_result = await _handle; // nil (error — no result)
// Error propagates to await-er
try {
_result = await _handle;
} catch {
print f"Async error: {_exception}";
};_handle = spawn { riskyOperation(); };
try {
_result = await _handle;
} catch {
_result = "fallback";
};_handle = spawn {
for "_i" from 0 to 100 step 10 do {
_thisScript setProgress _i;
sleep 0.5;
};
return "complete";
};
// Check progress (non-suspending)
_progress = _handle getProgress; // 0-100_data = await (spawn { fetchData(); });
_processed = await (spawn { process(_data); });
_saved = await (spawn { save(_processed); });_handles = [];
for "_i" from 0 to 9 do {
_handles pushBack (spawn { doWorkUnit(_i); });
};
_race = PromiseAll _handles timeout 30;
_results = await _race;
if (isNil "_results") then {
{ terminate _x } forEach _handles;
print "Work timed out";
};spawn { diag_log "background task"; }; // ignore handlespawn {
_myHandle = _thisScript; // reference to own handle
sleep 5;
// _myHandle is now the handle of this spawn
};| Feature | SQF | SQ# |
|---|---|---|
| Threading | Same scheduler only | Cross-scheduler, cross-thread |
| C# interop | Not possible | await handle.ToTask() |
| Cancellation |
terminate only |
terminate + CancellationToken
|
| Error handling | Silent fail | Exceptions propagate |
| Combinators | None |
PromiseAll, PromiseRace, PromiseAny
|
| Timeout | waitUntil [h, t] |
handle timeout seconds |
| Unscheduled await | ❌ | ❌ (must be scheduled) |
- Concurrency — schedulers, fibers, spawnOn
- spawn — create async handle
- await — wait for handle
- timeout — race against timer
- terminate — cancel handle
- scriptDone — check status
- Getting Started
- Language Guide
- Type System
- Control Flow
- Functions & Code
- Strings & Text
- Arrays & Collections
- Concurrency
- Promise System
- Thread Safety
- Host API & Embedding
- CLI Tool
- Bytecode Reference
- Multiplayer
- Syntax Sugar
- Optimization Guide
- Benchmarks
- count
- select
- pushBack
- append
- deleteAt
- deleteRange
- resize
- reverse
- sort
- find
- in
- forEach
- freeze
- thaw
- isFrozen
- currentScheduler
- clientOwner
- allSchedulers
- schedulerName
- schedulerExists
- schedulerBudget
- setSchedulerBudget
- fiberCount
- readyFiberCount
- waitingFiberCount
- schedulerLoad
- sendTo