OLD | NEW |
(Empty) | |
| 1 # Message pipes |
| 2 |
| 3 Message pipes are the primary communication mechanism between Mojo programs. A |
| 4 *message pipe* is a point-to-point (with each side being called a message pipe |
| 5 *endpoint*), bidirectional message passing mechanism, where messages may contain |
| 6 both data and Mojo handles. |
| 7 |
| 8 It's important to understand that a message pipe is a "transport": it provides a |
| 9 way for data and handles to be sent between Mojo programs. The system is unaware |
| 10 of the meaning of the data or of the handles (other than their intrinsic |
| 11 properties). |
| 12 |
| 13 That said, Mojo provides a *standard* way of communicating over message pipes, |
| 14 namely via a standardized protocol together with [Mojom IDL](mojom.md) files. |
| 15 |
| 16 ## Messages |
| 17 |
| 18 A *message* consists of two things: |
| 19 * a finite sequence of bytes, and |
| 20 * a finite sequence of Mojo handles. |
| 21 |
| 22 Both of these are determined when the message is sent (or *written*). Messages |
| 23 are *framed* in the sense that they are "atomic" units: they are sent and |
| 24 received (or *read*) as entire units, not just by Mojo programs themselves but |
| 25 by the system, which is aware of and enforces the message boundaries. |
| 26 |
| 27 (Note on terminology: We'll use "send" and "write" interchangeably, and |
| 28 similarly for "receive" and "read". "Write" and "read" correspond more closely |
| 29 to the names usually given to the basic Mojo operations, e.g., |
| 30 `MojoWriteMessage()` and `MojoReadMessage()`. |
| 31 |
| 32 ## Asynchronous operation and queueing |
| 33 |
| 34 Message pipes are *asynchronous* in the sense that sent messages do not have |
| 35 intrinsic response messages mediated/enforced by the system. (This is different |
| 36 from saying that message write/read are asynchronous operations: these |
| 37 operations are actually synchronous and complete "immediately". However, note |
| 38 that reading a message is "nonblocking" in the sense that it will fail if a |
| 39 message is not available to be read. Thus a message must be waited for, and the |
| 40 combined wait-then-read may form an asynchronous pattern.) |
| 41 |
| 42 To allow message writes to complete immediately, messages are queued. Indeed, |
| 43 one can understand a message pipe as a pair of queues, one in each direction. |
| 44 Each endpoint has opposite notions of incoming and outgoing queues (recall that |
| 45 message pipes have a pair of endpoints). |
| 46 |
| 47 Writing a message to an endpoint then simply entails enqueueing that message on |
| 48 that endpoint's outgoing queue (which is the *peer* endpoint's incoming queue). |
| 49 Reading a message from an endpoint is just dequeueing a message from that |
| 50 endpoint's incoming queue (which is the peer endpoint's outgoing queue). |
| 51 |
| 52 Queueing is unlimited. Why? The problem is that limiting queueing exposes Mojo |
| 53 programs to complex deadlock problems: |
| 54 * One way of limiting queue sizes is to block the sender if the queue is "full". |
| 55 However, the receiver may not be able or willing to consume messages until the |
| 56 sender does something else (and this is often the case in asynchronous |
| 57 programming). For example, perhaps the putative "receiver" does not yet even |
| 58 have a handle to the endpoint yet, and that handle is sent in a message (over |
| 59 some other message pipe). |
| 60 * Another way would be to have the write fail if the queue is full. Then the |
| 61 sender would want to additionally queue on its side. The thread would continue |
| 62 running and, e.g., run its message loop. However, sender-side queueing |
| 63 basically makes it impossible for the sender to transfer that endpoint |
| 64 (handle), at least until the sender-side queue is cleared. However, the |
| 65 receiver may not be able/willing to proceed until the sender has transferred |
| 66 the aforementioned endpoint. |
| 67 |
| 68 Thus we allow unlimited queueing. (**TODO(vtl)**: Probably we'll eventually |
| 69 allow "hard" queue limits to be set for the purposes of preventing |
| 70 denial-of-service. However, the response to overruns will be hard failures, in |
| 71 the sense that the message pipe may be destroyed, rather than soft, |
| 72 "recoverable" failures -- since those expose deadlock issues.) It is then up to |
| 73 Mojo programs to implement flow control in some way. (**TODO(vtl)**: Write more |
| 74 about this in the context of Mojom.) |
| 75 |
| 76 ## "Synchronous" operation |
| 77 |
| 78 **TODO(vtl)** |
OLD | NEW |