38 lines
1.0 KiB
GDScript3
38 lines
1.0 KiB
GDScript3
|
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)
|