A pitfall when using didSet and Task together - order can't be guaranteed

Task{} indeed breaks enqueue order, and it's been a long standing issue like that.

The way it is implemented today the Task initializer does not know where your code will end up running, so it has to enqueue on the global pool. If your code actually ends up calling into an actor immediately; you just lost ordering, like in this snippet:

Task {   
  await someActor.hello()
}

because of the "hop to global -> (reorderings may happen, something else may have enqueued on actor already in the meantime) -> hop to actor, run the actor method".

We are proposing to fix this via Task starting on the target actor which would take the shape of Task { [isolated target] await target.hello() } or doing this also automatically but if you want the guarantee you'd want to spell it out like that...

Ongoing proposal about this over here: Closure isolation control

11 Likes