stick-the-quick/util/Task.gd

38 lines
1.0 KiB
GDScript

class_name Task extends RefCounted
## Promise-like abstraction for (hopefully) safer concurrency.
signal _sig_finished
## Value returned by task. Null if, but not only if, task has not finished.
var result: Variant = null
var _finished := false
## Awaits the given Callable concurrently and reports back when it finishes.
func _init(thunk: Callable) -> void:
var coro := func() -> void:
result = await thunk.call()
_finished = true
_sig_finished.emit()
coro.call()
## Returns true iff the task has finished.
func is_finished() -> bool:
return _finished
## Waits for the task to finish (if necessary) and returns its result.
func sync() -> Variant:
if not _finished:
await _sig_finished
return result
## Creates a Task which can only finish when all subtasks have finished.
##
## Returns an array of the tasks' results in the same respective order.
static func group(subtasks: Array[Task]) -> Task:
var thunk := func() -> Array:
var results := []
for task in subtasks:
results.push_back(await task.sync())
return results
return Task.new(thunk)