[concurrency-interest] Coroutine-like control transfer?

David Holmes davidcholmes at aapt.net.au
Wed Aug 28 21:23:23 EDT 2013


Hi Charles,

Can you clarify exactly what semantics you want for your "co-routines". All
your suggested implementations involve switching threads and then waiting
for the co-routine to complete - so why not just execute it directly in the
first place?

David

> -----Original Message-----
> From: concurrency-interest-bounces at cs.oswego.edu
> [mailto:concurrency-interest-bounces at cs.oswego.edu]On Behalf Of Charles
> Oliver Nutter
> Sent: Thursday, 29 August 2013 7:36 AM
> To: concurrency-interest
> Subject: [concurrency-interest] Coroutine-like control transfer?
>
>
> I've been struggling for years to find the right (i.e. fastest) way to
> do a coroutine-like control transfer between two threads, and I
> figured I'd try asking here again...
>
> What I need to emulate is a true coroutine, where a thread transfers
> execution (ip and stack) to a different piece of code, that code runs
> for a while, and then execution transfers back. There's always exactly
> one piece of code executing at a given time, since there's literally
> only one thread bouncing between stacks.
>
> On the JVM, where we don't have real coroutines, the best we can do is
> to emulate this with threads (ignoring bytecode-weaving stack tricks
> like Kilim for the moment). I do not believe any of the structures in
> j.u.concurrent currently have this exact pattern in mind.
>
> The patterns I've used to emulate this:
>
> 1. Explicit park/unpark.
>
> The parent thread starts up the coroutine, which immediately parks
> itself. Parent thread wakes up coroutine by unparking it and giving it
> an initial value, at which point parent parks itself. Child runs for a
> bit, then unparks parent, gives it a value, and parks itself.
>
> This is logically closest to what I want, but the park/unpark
> operations are too expensive for fast transfers. This mechanism ended
> up being the slowest way when measuring raw transfer rate (i.e. very
> little work being done between transfers)
>
> 2. SynchronousQueue
>
> Instead of using explicit parking and unparking, the parent pushes a
> value on child's sync queue, and then waits on its own sync queue.
> Child signals parent by pushing a value on parent's sync queue and
> then waits on its own.
>
> This was about 3x faster than explicit park/unpark.
>
> 3. Exchanger
>
> Substitute Exchanger for SynchronousQueue, where the "take" operation
> just exchanges null and the "put" operation ignores the result. This
> was the fastest...around 15x faster than explicit park/unpark and 5x
> faster than SynchronousQueue
>
> 4. Just spin
>
> Do nothing but spin on a null volatile field waiting for it to become
> non-null. Another 3x faster than Exchanger.
>
> ...
>
> It seems like I'm building a conceptually simple pattern on top of
> structures not designed for it (or rather, designed for more complex
> patterns). In SynchronousQueue's case, I have to do two put/take
> operations for every transfer. With Exchanger, two exchanges. What I
> really want is something like LockSupport.park/unpark that's more like
> LockSupport.parkMeAndUnparkHimPassingValue(value), explicitly passing
> control and a value to the other thread.
>
> What am I missing? Do I need to hand-roll this?
>
> - Charlie
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
> -----
> No virus found in this message.
> Checked by AVG - www.avg.com
> Version: 2013.0.3392 / Virus Database: 3211/6614 - Release Date: 08/27/13
>



More information about the Concurrency-interest mailing list