lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


From experience using nurseries for over 3 years in a large, production, Python app:  cancelling children on non-error scope exit is not the desired semantics, 95% of the time.

I think it depends on what the "tasks" are for.  If a task is a kind of job that runs in a finite amount of time and produces some useful result/computation, then why would you issue a return statement before they have completed?  Don't you have to wait for them to complete in order to get their results, and then use those to produce the return value or as input to a subsequent computation?  And if that is not the case, then I would argue that those tasks are not essential, and could just as well be cancelled upon issuing the return statement (which causes control flow to leave the current scope).

If we insist on waiting for the tasks to complete whenever we leave the scope for non-error reasons, then we also have an asymmetry/inconsistency of behavior when leaving the scope; i.e., the fate of the tasks depends on the precise way in which we leave the scope, which I think makes programs harder to reason about in a way.

In my own use cases of coroutines (an event-driven game which happens to be in C++, but the ideas are the same[1]) I've found the right default to be that all tasks get cancelled when leaving a scope by any means.  Any tasks that we want to complete must be explicitly awaited on (either on their own, or with e.g. wait_for_any, wait_for_all, etc.).

David
[1] Currently C++ coroutines are not able to yield at scope exit, unlike Lua.  And so therefore, cancellation-on-scope-exit is the only option (and even that cannot be implemented in an ideal way because sometimes even cancellation requires yielding).  But I actually think it can be the right default in some applications.  But I do understand that it might not be the right default in all cases; some C++ developers are currently expressing dismay at the fact that coroutines cannot yield within destructors.

On Sun, Sep 25, 2022 at 8:59 PM John Belmonte <john@neggie.net> wrote:
On Mon, Sep 26, 2022 at 1:41 AM Jorge Visca <xxopxe@gmail.com> wrote:
After some (rather murky) thinking, I believe that the natural behavior
for a "task" going out of scope is to be killed right away.

To clarify first: if the nursery scope exits by exception, the children will be cancelled.  (The code posted so far doesn't quite implement this properly, but that's coming next.)  So what you mention is regarding the non-error case.

From experience using nurseries for over 3 years in a large, production, Python app:  cancelling children on non-error scope exit is not the desired semantics, 95% of the time.  The articles haven't delved into the practical uses of nurseries, so I can understand this not being evident.  Fortunately, the nursery API will have a cancel method (also not yet implemented), which can be called just before the end of the scope, if that's the needed behavior.