Hi, I made it by creating a small utility called Counter and using lambda functions to make different coroutine blocks.:
class_name Counter
signal completed
var _counter: int
var _total: int
func _init(p_total: int):
_total = p_total
_counter = 0
func submit():
_counter = _counter + 1
if _counter == _total:
completed.emit()
In my main functions:
func main():
var jobs = Counter.new(3) # I have 3 jobs here
var job_1 = func():
await download_coroutine_1
jobs.submit()
job_1.call()
var job_2 = func():
await download_coroutine_2
jobs.submit()
job_2.call()
var job_3 = func():
await download_coroutine_3
jobs.submit()
job_3.call()
await jobs.completed
Thanks for this feedback. I think that could work.
In your example, don’t you still need to invoke the lambdas? And do you do that without awaits so you only block at the bottom?
I liked kienhoang’s answer and made a version that fires off all of the jobs in quick succession after you queue them up. Create this object, queue up as many objects as you’d like (with their params, start method, and finished signal), and then run them all at once with run_all(). Await completed on the object for them all to finish.
If you want to do stuff with the objects’ return params as they complete, connect your own functions to their signals before calling run_all.
extends Object
class_name ParallelCoroutines
signal completed
var queued_coroutines:Array[Dictionary]
var total_count: int
var completed_count: int
func append(object:Object, params:Array, call_method:StringName, complete_signal:StringName):
queued_coroutines.append({'object': object, 'params': params, 'call_method': call_method, 'complete_signal': complete_signal})
func run_all():
total_count = queued_coroutines.size()
for routine in queued_coroutines:
var object:Object = routine['object']
var params:Array = routine['params']
var call_method:StringName = routine['call_method']
var complete_signal:StringName = routine['complete_signal']
object.callv(call_method, params)
object.connect(complete_signal, _on_completed)
func _on_completed(a=null, b=null, c=null, d=null, e=null, f=null, g=null): # I don't know how else to allow but ignore parameters
completed_count = completed_count + 1
if completed_count == total_count:
completed.emit()