2 ms·
> First, a linear sequence of asynchronous operations does not appear in a linear piece of code. Instead, it is spread across a series of many small functions.
by rdtsc 10y ago
> First, a linear sequence of asynchronous operations does not appear in a linear piece of code.
Instead, it is spread across a series of many small functions.
Largely unrelated to Rust, but I want to point out that that is a powerful insight. It took me a while to internalize that. Once you see it, you'll understand why asynchronous, callback-based programming is usually inferior to other models (green threads, channel, lightweight processes and yes, threads). There are some exceptions for course, say when callback chains are short, like a web proxy, in the an embedded world, or a short demo code someone pasted on SO.
Another way to think about it is that "an sequence of callbacks forms an ad-hoc execution context, like a thread almost, except it is spread all through various functions, not very well specified, not in one single place".
Now perhaps in this style you can avoid CPU locks, but if callbacks are used for concurrent IO, you are back to the the need to protect global data from concurrent modifications. For example, if a callback chain starts, say cb1, cb2, cb3 but stops at cb2 while it was modifying some global data. Then another user request (or other such event) comes and it starts running cb1, cb2, cb3. It will possibly start modifying the same global data before it was in a consistent state. Next thing you know is you need something like a lock or semaphore. And sure enough such a thing exists, here is an example in Twisted: http://twistedmatrix.com/documents/8.1.0/api/twisted.internet.defer.DeferredSemaphore.html http://twistedmatrix.com/documents/8.1.0/api/twisted.interne...