Legend:

Were we to call chardev_read() from two different fibrils A and B concurrently, the server fibril would see some mixture of the sequence (AR1, AR2) with (BR1, BR2), e.g. (AR1, BR1, AR2, BR2) which would be incorrect from the server point of view. Note that the server has no way of telling which request belongs to which operation.

37

Were we to call mysrv_read() from two different fibrils A and B concurrently, the server fibril would see some mixture of the sequence (AR1, AR2) with (BR1, BR2), e.g. (AR1, BR1, AR2, BR2) which would be incorrect from the server point of view. Note that the server has no way of telling which request belongs to which operation.

38

38

39

We often want to allow such function to be called concurrently in different fibrils. chardev_read() can block so we cannot serialize calls to it. If we stay with the character device example, we often want to allow one fibril to call chardev_write() while another is blocked in chardev_read().

39

We often want to allow such function to be called concurrently in different fibrils. mysrv_read() can block so we cannot serialize calls to it. If we took a character device as an example, we often want to allow one fibril to write while another fibril is blocked in a read operation.

Now we can run chardev_read() in parallel in any number of fibrils/threads. Each IPC request has a context (the exchange) so the different parallel operations will not mix up.

90

Now we can run mysrv_read() in parallel in any number of fibrils/threads. Each IPC request has a context (the exchange) so the different parallel operations will not mix up.

91

91

92

92

Behind the scenes the async framework will do the magic necessary to distinguish the exchanges. In the current implementation it clones the session phone and uses as many separate physical connections as there are concurrent exchanges. It caches the open connections to avoid setting them up and tearing them down too often.