Closed hniksic closed 4 years ago
There was a contribution of a Promise
class that can be found in curio/promise.py. However, it's not documented and I've been pondering what to do with it long-term.
I had considered the idea of making a Future
for Curio, but possibly along the same line of thinking as the UniversalEvent
and UniversalQueue
classes--meaning that I'd try to make it something that could be used from threads or async in any combination.
Short answer: I'd consider something like this. I'll take a look at the attached example as well.
Yury Selivanov has gone on record saying that Futures are going away in asyncio.
So far as I know, Yury's comment pertains to the use of Futures in the internal implementation of asyncio. This bug pertains to supporting a Future/Promise as a user-level synchronization primitive between Curio tasks, much like an Event
object. I'm open to that.
@agronholm I didn't know that, do you have a link with more information? @dabeaz explained why this is not directly relevant to this issue, but it's still an interesting development.
Would a synchronization queue a cleaner programming model than futures/promises? If one programs with concurrent tasks(threads or async tasks...) and synchronization queues only, then one can achieve concurrency with pure synchronized API.
Do you have an example implementation of such a thing somewhere?
Apple’s Grand Central Dispatch (often abbreviated as GCD or libdispatch) is built around a concept of serial and concurrent queues.
Best Regards Ilya Kulakov
On Sep 3, 2018, at 11:50 AM, Alex Grönholm notifications@github.com wrote:
Do you have an example implementation of such a thing somewhere?
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.
Occasionally I find
asyncio.Future
useful as a synchronization primitive in its own right, and I'm wondering if there is a corresponding construct in curio. Please note that I'm aware that curio is not built around futures the way asyncio is - this issue is specifically about using a future as a tool to transfer data between different coroutines. Let me illustrate that with two examples.Example 1: broadcasting messages to clients running in separate coroutines.
Code in this SO answer periodically broadcasts data to multiple running coroutines. Each of the coroutines await on a shared
Future
, and the broadcaster usesset_result()
to send them all a message. The broadcaster immediately sets the variable to a new shared future, which results in the coroutines that receive the message immediately start waiting for the new one.Example 2: Synchronizing between a single producer and multiple consumers.
Another SO answer contains a slightly more involved example. It does something that looks simple: runs two aggregate functions (coroutines) in parallel over the same iterator without buffering. The code needs to transmit each produced value to multiple consumers and relies on a similar technique, using a
Future
as a lightweight broadcasting medium. The future is especially convenient because it already carries a payload value (which can in the general case also be an exception) but is otherwise really lightweight compared to primitives inspired bythreading
.The closest curio alternative I've found is to use an
Event
and simply attach a value to it. However, doing for the second example results in an execution time 1.2x slower than asyncio - reproducible example attached. (BTW, greenlet's explicit switching appears an order of magnitude faster than either - see the above SO answer for code.)Would curio actually benefit from a future-like synchronization device, or am I doing something completely wrong?