3 ms·
A problem I don’t have a good answer to is how to extend conditions (or even exceptions) to async programming models. Two problems are: 1. some code may fail
by dan-robertson 6y ago
A problem I don’t have a good answer to is how to extend conditions (or even exceptions) to async programming models.
Two problems are:
1. some code may fail multiple times (with non-async code, once an exception is caught the program can’t throw another one from the same dynamic extent of the try block; similarly once a restart is invoked and control is transferred, a condition won’t be signalled from the same dynamic extent where the restart was bound (for the purpose of this clause, we consider a retry restart to mint a new dynamic extent to bind the restart in again after retrying))
2. Some computation may happen after you don’t care about its result because a parallel dependency has failed. E.g. suppose you have some rate limiter where you pass an async function, get a promise for it’s result, and the rate limited will queue your function to be called soon but with the condition that it will only allow say 5 calls to be in flight. Now you have some resource-downloading function which puts many separate download requests into the ratelimiter in parallel, and combines the results in such a way that the whole download fails if any request fails. But now if an early request fails, your function will continue trying to download all the other resources even though it doesn’t care about the result now that it has failed. You could imagine having a way to cancel promises and maybe you would be clever and write really solid programs and never have issues but to me this seems to be inviting very difficult to debug problems (just like expecting any thread to be killed at any random point (or at least a bunch of different points) would make correct multithreaded programming harder.
Perhaps a more succinct description of problem 2 is that unwinding the “stack” isn’t well-defined with an async programming model because “stack” doesn’t really mean the call stack from the scheduler you whatever bit of async computation you happen to be doing, but rather the combined dynamic scope from everything that started the computation and is currently awaiting its completion.
A related and, I think, very useful thing to have is a way to represent computations which may signal conditions or be restarted. I think CL doesn’t have a great story for this (threading isn’t really a part of the language though). An example use case would be some program which has to process some stream of events. If it gets stuck on one or some, you may want to continue processing the rest of the events while deciding what restart to invoke for the problematic ones. Perhaps an effect system could help with this.
- phoe-krk 6y agoI'll be frank: my book does not touch this topic in the slightest, and this is an open question. Common Lisp does not have any asynchronous features built in and, as I've said in some earlier comment, the condition system is fully synchronous. This topic is still waiting to be explored, either with an extension of Common Lisp or a completely different language that permits asynchronous programming with an adaptation of the condition system to this programming paradigm.