coroutines,callbacks,message-queues

This page is about analysis of different async flow coordination techniques. It analyses the pros and cons of different techniques.

Before coroutines, there wasn't much choice. We had callbacks and vwait. Now coroutines are available. Some consider it as a Holy-grail for event-based programming.

There are two problems with call-backs.

  • Code/Flow is fragmented, into two different blocks. To follow the flow, one has to jump around proc stubs to get an idea.
  • Nested vwait problem.

One's program has to use the global vwait. If one makes a vwait, then one has to ensure that it does not depend on outer vwait.Then deadlock happens.

Coroutines world

Coroutines seems to elegantly solve the above two problems.

  • yield happens in a single proc or code-block. No Fragmentation of code-blocks.
  • There is no nested dependency relation like vwait, when a code waits on a yield.

Coroutines - problems

One of the major traits of robust software architecture is, to the extent possible components should be loosely coupled.

Coroutines create a tighter coupling. To understand this, one has to analyse coroutines under different scenarios.

Coroutines yield, has lot of implicit assumptions. It assumes there is only one caller or context of calling. Assuming a code, where there are multiple callers for this coroutine. Then yield can return, out of any such call.

In most such cases, the flow cannot continue, ignoring who called the coroutine.

The following is the programming style, I can think of which address this issue. Each coroutine should be associated with a message queue.(Inspiration Erlang)

These are the operations defined on the message queue.

 1. put message on a message queue
 2. wait for any new message.
 3. wait for any new message that satisfies a filter condition.
 4. get message (possible delete too)
 5. Create a message queue that associates a coroutine with it.

The caller invokes put_message. The caller implicitly or explicitly gives the caller/context/reply-id information in the message.

The put_message invokes the coroutine synchronously or async (after 0 <coroutine>)

The coroutine instead of yield, should call wait_message. If multiple callers are expected and if it wants reply from one caller, it should invoke wait_message with filter.

The yield should be done in the wait_message procs, not explicitly in the coroutine.

I feel coroutine with message queue based co-ordination is needed in most softwares of bigger complexity.

APN See Fiber.

PYK and ycl coro relay.