xref: /aosp_15_r20/external/libchrome/mojo/public/c/system/README.md (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker# Mojo C System API
2*635a8641SAndroid Build Coastguard WorkerThis document is a subset of the [Mojo documentation](/mojo/README.md).
3*635a8641SAndroid Build Coastguard Worker
4*635a8641SAndroid Build Coastguard Worker[TOC]
5*635a8641SAndroid Build Coastguard Worker
6*635a8641SAndroid Build Coastguard Worker## Overview
7*635a8641SAndroid Build Coastguard WorkerThe Mojo C System API is a lightweight API (with an stable, forward-compatible
8*635a8641SAndroid Build Coastguard WorkerABI) upon which all higher-level public Mojo APIs are built.
9*635a8641SAndroid Build Coastguard Worker
10*635a8641SAndroid Build Coastguard WorkerThis API exposes the fundamental capabilities to: create, read from, and write
11*635a8641SAndroid Build Coastguard Workerto **message pipes**; create, read from, and write to **data pipes**; create
12*635a8641SAndroid Build Coastguard Worker**shared buffers** and generate sharable handles to them; wrap platform-specific
13*635a8641SAndroid Build Coastguard Workerhandle objects (such as **file descriptors**, **Windows handles**, and
14*635a8641SAndroid Build Coastguard Worker**Mach ports**) for seamless transit over message pipes; and efficiently watch
15*635a8641SAndroid Build Coastguard Workerhandles for various types of state transitions. Finally, there are also APIs to
16*635a8641SAndroid Build Coastguard Workerbootstrap Mojo IPC between two processes.
17*635a8641SAndroid Build Coastguard Worker
18*635a8641SAndroid Build Coastguard WorkerThis document provides a brief guide to API usage with example code snippets.
19*635a8641SAndroid Build Coastguard WorkerFor a detailed API references please consult the headers in
20*635a8641SAndroid Build Coastguard Worker[//mojo/public/c/system](https://cs.chromium.org/chromium/src/mojo/public/c/system/).
21*635a8641SAndroid Build Coastguard Worker
22*635a8641SAndroid Build Coastguard Worker### A Note About Multithreading
23*635a8641SAndroid Build Coastguard Worker
24*635a8641SAndroid Build Coastguard WorkerThe Mojo C System API is entirely thread-agnostic. This means that all functions
25*635a8641SAndroid Build Coastguard Workermay be called from any thread in a process, and there are no restrictions on how
26*635a8641SAndroid Build Coastguard Workermany threads can use the same object at the same time.
27*635a8641SAndroid Build Coastguard Worker
28*635a8641SAndroid Build Coastguard WorkerOf course this does not mean you can completely ignore potential concurrency
29*635a8641SAndroid Build Coastguard Workerissues -- such as a handle being closed on one thread while another thread is
30*635a8641SAndroid Build Coastguard Workertrying to perform an operation on the same handle -- but there is nothing
31*635a8641SAndroid Build Coastguard Workerfundamentally incorrect about using any given API or handle from multiple
32*635a8641SAndroid Build Coastguard Workerthreads.
33*635a8641SAndroid Build Coastguard Worker
34*635a8641SAndroid Build Coastguard Worker### A Note About Synchronization
35*635a8641SAndroid Build Coastguard Worker
36*635a8641SAndroid Build Coastguard WorkerEvery Mojo API call is non-blocking and synchronously yields some kind of status
37*635a8641SAndroid Build Coastguard Workerresult code, but the call's side effects -- such as affecting the state of
38*635a8641SAndroid Build Coastguard Workerone or more handles in the system -- may or may not occur asynchronously.
39*635a8641SAndroid Build Coastguard Worker
40*635a8641SAndroid Build Coastguard WorkerMojo objects can be observed for interesting state changes in a way that is
41*635a8641SAndroid Build Coastguard Workerthread-agnostic and in some ways similar to POSIX signal handlers: *i.e.*
42*635a8641SAndroid Build Coastguard Workeruser-provided notification handlers may be invoked at any time on arbitrary
43*635a8641SAndroid Build Coastguard Workerthreads in the process. It is entirely up to the API user to take appropriate
44*635a8641SAndroid Build Coastguard Workermeasures to synchronize operations against other application state.
45*635a8641SAndroid Build Coastguard Worker
46*635a8641SAndroid Build Coastguard WorkerThe higher level [system](/mojo/README.md#High-Level-System-APIs) and
47*635a8641SAndroid Build Coastguard Worker[bindings](/mojo/README.md#High-Level-Bindings-APIs) APIs provide helpers to
48*635a8641SAndroid Build Coastguard Workersimplify Mojo usage in this regard, at the expense of some flexibility.
49*635a8641SAndroid Build Coastguard Worker
50*635a8641SAndroid Build Coastguard Worker## Result Codes
51*635a8641SAndroid Build Coastguard Worker
52*635a8641SAndroid Build Coastguard WorkerMost API functions return a value of type `MojoResult`. This is an integral
53*635a8641SAndroid Build Coastguard Workerresult code used to convey some meaningful level of detail about the result of a
54*635a8641SAndroid Build Coastguard Workerrequested operation.
55*635a8641SAndroid Build Coastguard Worker
56*635a8641SAndroid Build Coastguard WorkerSee [//mojo/public/c/system/types.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/types.h)
57*635a8641SAndroid Build Coastguard Workerfor different possible values. See documentation for individual API calls for
58*635a8641SAndroid Build Coastguard Workermore specific contextual meaning of various result codes.
59*635a8641SAndroid Build Coastguard Worker
60*635a8641SAndroid Build Coastguard Worker## Handles
61*635a8641SAndroid Build Coastguard Worker
62*635a8641SAndroid Build Coastguard WorkerEvery Mojo IPC primitive is identified by a generic, opaque integer handle of
63*635a8641SAndroid Build Coastguard Workertype `MojoHandle`. Handles can be acquired by creating new objects using various
64*635a8641SAndroid Build Coastguard WorkerAPI calls, or by reading messages which contain attached handles.
65*635a8641SAndroid Build Coastguard Worker
66*635a8641SAndroid Build Coastguard WorkerA `MojoHandle` can represent a message pipe endpoint, a data pipe consumer,
67*635a8641SAndroid Build Coastguard Workera data pipe producer, a shared buffer reference, a wrapped native platform
68*635a8641SAndroid Build Coastguard Workerhandle such as a POSIX file descriptor or a Windows system handle, a trap object
69*635a8641SAndroid Build Coastguard Worker(see [Signals & Traps](#Signals-Traps) below), or a process invitation (see
70*635a8641SAndroid Build Coastguard Worker[Invitations](#Invitations) below).
71*635a8641SAndroid Build Coastguard Worker
72*635a8641SAndroid Build Coastguard WorkerMessage pipes, data pipes, shared buffers, and platform handles can all be
73*635a8641SAndroid Build Coastguard Workerattached to messages and sent over message pipes. Traps are an inherently
74*635a8641SAndroid Build Coastguard Workerprocess-local concept, and invitations are transmitted using special dedicated
75*635a8641SAndroid Build Coastguard WorkerAPIs.
76*635a8641SAndroid Build Coastguard Worker
77*635a8641SAndroid Build Coastguard WorkerAny `MojoHandle` may be closed by calling `MojoClose`:
78*635a8641SAndroid Build Coastguard Worker
79*635a8641SAndroid Build Coastguard Worker``` c
80*635a8641SAndroid Build Coastguard WorkerMojoHandle x = DoSomethingToGetAValidHandle();
81*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoClose(x);
82*635a8641SAndroid Build Coastguard Worker```
83*635a8641SAndroid Build Coastguard Worker
84*635a8641SAndroid Build Coastguard WorkerIf the handle passed to `MojoClose` was a valid handle, it will be closed and
85*635a8641SAndroid Build Coastguard Worker`MojoClose` returns `MOJO_RESULT_OK`. Otherwise it returns
86*635a8641SAndroid Build Coastguard Worker`MOJO_RESULT_INVALID_ARGUMENT`.
87*635a8641SAndroid Build Coastguard Worker
88*635a8641SAndroid Build Coastguard WorkerSimilar to native system handles on various popular platforms, `MojoHandle`
89*635a8641SAndroid Build Coastguard Workervalues may be reused over time. Thus it is important to avoid logical errors
90*635a8641SAndroid Build Coastguard Workerwhich lead to misplaced handle ownership, double-closes, *etc.*
91*635a8641SAndroid Build Coastguard Worker
92*635a8641SAndroid Build Coastguard Worker## Message Pipes
93*635a8641SAndroid Build Coastguard Worker
94*635a8641SAndroid Build Coastguard WorkerA message pipe is a bidirectional messaging channel which can carry arbitrary
95*635a8641SAndroid Build Coastguard Workerunstructured binary messages with zero or more `MojoHandle` attachments to be
96*635a8641SAndroid Build Coastguard Workertransferred from one end of a pipe to the other. Message pipes work seamlessly
97*635a8641SAndroid Build Coastguard Workeracross process boundaries or within a single process.
98*635a8641SAndroid Build Coastguard Worker
99*635a8641SAndroid Build Coastguard Worker[Invitations](#Invitations) provide the means to bootstrap one or more
100*635a8641SAndroid Build Coastguard Workerprimordial cross-process message pipes between two processes. Once such a pipe
101*635a8641SAndroid Build Coastguard Workeris established, additional handles -- including other message pipe handles --
102*635a8641SAndroid Build Coastguard Workermay be sent to a remote process using that pipe (or in turn, over other pipes
103*635a8641SAndroid Build Coastguard Workersent over that pipe, or pipes sent over *that* pipe, and so on...)
104*635a8641SAndroid Build Coastguard Worker
105*635a8641SAndroid Build Coastguard WorkerThe public C System API exposes the ability to read and write messages on pipes
106*635a8641SAndroid Build Coastguard Workerand to create new message pipes.
107*635a8641SAndroid Build Coastguard Worker
108*635a8641SAndroid Build Coastguard WorkerSee [//mojo/public/c/system/message_pipe.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/message_pipe.h)
109*635a8641SAndroid Build Coastguard Workerfor detailed message pipe API documentation.
110*635a8641SAndroid Build Coastguard Worker
111*635a8641SAndroid Build Coastguard Worker### Creating Message Pipes
112*635a8641SAndroid Build Coastguard Worker
113*635a8641SAndroid Build Coastguard Worker`MojoCreateMessagePipe` can be used to create a new message pipe:
114*635a8641SAndroid Build Coastguard Worker
115*635a8641SAndroid Build Coastguard Worker``` c
116*635a8641SAndroid Build Coastguard WorkerMojoHandle a, b;
117*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoCreateMessagePipe(NULL, &a, &b);
118*635a8641SAndroid Build Coastguard Worker```
119*635a8641SAndroid Build Coastguard Worker
120*635a8641SAndroid Build Coastguard WorkerAfter this snippet, `result` should be `MOJO_RESULT_OK` (it's really hard for
121*635a8641SAndroid Build Coastguard Workerthis to fail!), and `a` and `b` will contain valid Mojo handles, one for each
122*635a8641SAndroid Build Coastguard Workerend of the new message pipe.
123*635a8641SAndroid Build Coastguard Worker
124*635a8641SAndroid Build Coastguard WorkerAny messages written to `a` are eventually readable from `b`, and any messages
125*635a8641SAndroid Build Coastguard Workerwritten to `b` are eventually readable from `a`. If `a` is closed at any point,
126*635a8641SAndroid Build Coastguard Worker`b` will eventually become aware of this fact; likewise if `b` is closed, `a`
127*635a8641SAndroid Build Coastguard Workerwill become aware of that.
128*635a8641SAndroid Build Coastguard Worker
129*635a8641SAndroid Build Coastguard WorkerThe state of these conditions can be queried and watched asynchronously as
130*635a8641SAndroid Build Coastguard Workerdescribed in the [Signals & Traps](#Signals-Traps) section below.
131*635a8641SAndroid Build Coastguard Worker
132*635a8641SAndroid Build Coastguard Worker### Creating Messages
133*635a8641SAndroid Build Coastguard Worker
134*635a8641SAndroid Build Coastguard WorkerMessage pipes carry message objects which may or may not be serialized. You can
135*635a8641SAndroid Build Coastguard Workercreate a new message object as follows:
136*635a8641SAndroid Build Coastguard Worker
137*635a8641SAndroid Build Coastguard Worker``` c
138*635a8641SAndroid Build Coastguard WorkerMojoMessageHandle message;
139*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoCreateMessage(nullptr, &message);
140*635a8641SAndroid Build Coastguard Worker```
141*635a8641SAndroid Build Coastguard Worker
142*635a8641SAndroid Build Coastguard WorkerNote that we have a special `MojoMessageHandle` type for message objects.
143*635a8641SAndroid Build Coastguard Worker
144*635a8641SAndroid Build Coastguard WorkerMessages may be serialized with attached data or unserialized with an
145*635a8641SAndroid Build Coastguard Workeropaque context value. Unserialized messages support lazy serialization, allowing
146*635a8641SAndroid Build Coastguard Workercustom serialization logic to be invoked only if and when serialization is
147*635a8641SAndroid Build Coastguard Workerrequired, e.g. when the message needs to cross a process or language boundary.
148*635a8641SAndroid Build Coastguard Worker
149*635a8641SAndroid Build Coastguard WorkerTo make a serialized message, you might write something like:
150*635a8641SAndroid Build Coastguard Worker
151*635a8641SAndroid Build Coastguard Worker``` c
152*635a8641SAndroid Build Coastguard Workervoid* buffer;
153*635a8641SAndroid Build Coastguard Workeruint32_t buffer_size;
154*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoAppendMessageData(message, nullptr, 6, nullptr, 0,
155*635a8641SAndroid Build Coastguard Worker                                          &buffer, &buffer_size);
156*635a8641SAndroid Build Coastguard Workermemcpy(buffer, "hello", 6);
157*635a8641SAndroid Build Coastguard Worker```
158*635a8641SAndroid Build Coastguard Worker
159*635a8641SAndroid Build Coastguard WorkerThis attaches a data buffer to `message` with at least `6` bytes of storage
160*635a8641SAndroid Build Coastguard Workercapacity. The outputs returned in `buffer` and `buffer_size` can be used by the
161*635a8641SAndroid Build Coastguard Workercaller to fill in the message contents.
162*635a8641SAndroid Build Coastguard Worker
163*635a8641SAndroid Build Coastguard WorkerMultiple calls to `MojoAppendMessageData` may be made on a single message
164*635a8641SAndroid Build Coastguard Workerobject, and each call appends to any payload and handles accumulated so far.
165*635a8641SAndroid Build Coastguard WorkerBefore you can transmit a message carrying data you must commit to never calling
166*635a8641SAndroid Build Coastguard Worker`MojoAppendMessageData` again. You do this by passing the
167*635a8641SAndroid Build Coastguard Worker`MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE` flag:
168*635a8641SAndroid Build Coastguard Worker
169*635a8641SAndroid Build Coastguard Worker``` c
170*635a8641SAndroid Build Coastguard WorkerMojoAppendMessageDataOptions options;
171*635a8641SAndroid Build Coastguard Workeroptions.struct_size = sizeof(options);
172*635a8641SAndroid Build Coastguard Workeroptions.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE;
173*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoAppendMessageData(message, &options, 0, nullptr, 0,
174*635a8641SAndroid Build Coastguard Worker                                          &buffer, &buffer_size);
175*635a8641SAndroid Build Coastguard Worker```
176*635a8641SAndroid Build Coastguard Worker
177*635a8641SAndroid Build Coastguard WorkerCreating lazily-serialized messages is also straightforward:
178*635a8641SAndroid Build Coastguard Worker
179*635a8641SAndroid Build Coastguard Worker``` c
180*635a8641SAndroid Build Coastguard Workerstruct MyMessage {
181*635a8641SAndroid Build Coastguard Worker  // some interesting data...
182*635a8641SAndroid Build Coastguard Worker};
183*635a8641SAndroid Build Coastguard Worker
184*635a8641SAndroid Build Coastguard Workervoid SerializeMessage(MojoMessageHandle message, uintptr_t context) {
185*635a8641SAndroid Build Coastguard Worker  struct MyMessage* my_message = (struct MyMessage*)context;
186*635a8641SAndroid Build Coastguard Worker
187*635a8641SAndroid Build Coastguard Worker  MojoResult result = MojoAppendMessageData(message, ...);
188*635a8641SAndroid Build Coastguard Worker  // Serialize however you like.
189*635a8641SAndroid Build Coastguard Worker}
190*635a8641SAndroid Build Coastguard Worker
191*635a8641SAndroid Build Coastguard Workervoid DestroyMessage(uintptr_t context) {
192*635a8641SAndroid Build Coastguard Worker  free((void*)context);
193*635a8641SAndroid Build Coastguard Worker}
194*635a8641SAndroid Build Coastguard Worker
195*635a8641SAndroid Build Coastguard WorkerMyMessage* data = malloc(sizeof(MyMessage));
196*635a8641SAndroid Build Coastguard Worker// initialize *data...
197*635a8641SAndroid Build Coastguard Worker
198*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoSetMessageContext(
199*635a8641SAndroid Build Coastguard Worker    message, (uintptr_t)data, &SerializeMessage, &DestroyMessage, nullptr);
200*635a8641SAndroid Build Coastguard Worker```
201*635a8641SAndroid Build Coastguard Worker
202*635a8641SAndroid Build Coastguard WorkerIf we change our mind and decide not to send the message, we can destroy it:
203*635a8641SAndroid Build Coastguard Worker
204*635a8641SAndroid Build Coastguard Worker``` c
205*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoDestroyMessage(message);
206*635a8641SAndroid Build Coastguard Worker```
207*635a8641SAndroid Build Coastguard Worker
208*635a8641SAndroid Build Coastguard WorkerNote that attempting to write a message will transfer ownership of the message
209*635a8641SAndroid Build Coastguard Workerobject (and any attached handles) into the message pipe, and there is therefore
210*635a8641SAndroid Build Coastguard Workerno need to subsequently call `MojoDestroyMessage` on that message.
211*635a8641SAndroid Build Coastguard Worker
212*635a8641SAndroid Build Coastguard Worker### Writing Messages
213*635a8641SAndroid Build Coastguard Worker
214*635a8641SAndroid Build Coastguard Worker``` c
215*635a8641SAndroid Build Coastguard Workerresult = MojoWriteMessage(a, message, nullptr);
216*635a8641SAndroid Build Coastguard Worker```
217*635a8641SAndroid Build Coastguard Worker
218*635a8641SAndroid Build Coastguard Worker`MojoWriteMessage` is a *non-blocking* call: it always returns
219*635a8641SAndroid Build Coastguard Workerimmediately. If its return code is `MOJO_RESULT_OK` the message will eventually
220*635a8641SAndroid Build Coastguard Workerfind its way to the other end of the pipe -- assuming that end isn't closed
221*635a8641SAndroid Build Coastguard Workerfirst, of course. If the return code is anything else, the message is deleted
222*635a8641SAndroid Build Coastguard Workerand not transferred.
223*635a8641SAndroid Build Coastguard Worker
224*635a8641SAndroid Build Coastguard WorkerIn this case since we know `b` is still open, we also know the message will
225*635a8641SAndroid Build Coastguard Workereventually arrive at `b`. `b` can be queried or watched to become aware of when
226*635a8641SAndroid Build Coastguard Workerthe message arrives, but we'll ignore that complexity for now. See
227*635a8641SAndroid Build Coastguard Worker[Signals & Traps](#Signals-Traps) below for more information.
228*635a8641SAndroid Build Coastguard Worker
229*635a8641SAndroid Build Coastguard Worker*** aside
230*635a8641SAndroid Build Coastguard Worker**NOTE**: Although this is an implementation detail and not strictly guaranteed
231*635a8641SAndroid Build Coastguard Workerby the System API, it is true in the current implementation that the message
232*635a8641SAndroid Build Coastguard Workerwill arrive at `b` before the above `MojoWriteMessage` call even returns,
233*635a8641SAndroid Build Coastguard Workerbecause `b` is in the same process as `a` and has never been transferred over
234*635a8641SAndroid Build Coastguard Workeranother pipe.
235*635a8641SAndroid Build Coastguard Worker***
236*635a8641SAndroid Build Coastguard Worker
237*635a8641SAndroid Build Coastguard Worker### Reading Messages
238*635a8641SAndroid Build Coastguard Worker
239*635a8641SAndroid Build Coastguard WorkerWe can read a new message object from a pipe:
240*635a8641SAndroid Build Coastguard Worker
241*635a8641SAndroid Build Coastguard Worker``` c
242*635a8641SAndroid Build Coastguard WorkerMojoMessageHandle message;
243*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoReadMessage(b, nullptr, &message);
244*635a8641SAndroid Build Coastguard Worker```
245*635a8641SAndroid Build Coastguard Worker
246*635a8641SAndroid Build Coastguard Workerand extract its data:
247*635a8641SAndroid Build Coastguard Worker
248*635a8641SAndroid Build Coastguard Worker``` c
249*635a8641SAndroid Build Coastguard Workervoid* buffer = NULL;
250*635a8641SAndroid Build Coastguard Workeruint32_t num_bytes;
251*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoGetMessageData(message, nullptr, &buffer, &num_bytes,
252*635a8641SAndroid Build Coastguard Worker                                       nullptr, nullptr);
253*635a8641SAndroid Build Coastguard Workerprintf("Pipe says: %s", (const char*)buffer);
254*635a8641SAndroid Build Coastguard Worker```
255*635a8641SAndroid Build Coastguard Worker
256*635a8641SAndroid Build Coastguard Worker`result` should be `MOJO_RESULT_OK` and this snippet should write `"hello"` to
257*635a8641SAndroid Build Coastguard Worker`stdout`.
258*635a8641SAndroid Build Coastguard Worker
259*635a8641SAndroid Build Coastguard WorkerIf we try were to try reading again now that there are no messages on `b`:
260*635a8641SAndroid Build Coastguard Worker
261*635a8641SAndroid Build Coastguard Worker``` c
262*635a8641SAndroid Build Coastguard WorkerMojoMessageHandle message;
263*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoReadMessage(b, nullptr, &message);
264*635a8641SAndroid Build Coastguard Worker```
265*635a8641SAndroid Build Coastguard Worker
266*635a8641SAndroid Build Coastguard WorkerWe'll get a `result` of `MOJO_RESULT_SHOULD_WAIT`, indicating that the pipe is
267*635a8641SAndroid Build Coastguard Workernot yet readable.
268*635a8641SAndroid Build Coastguard Worker
269*635a8641SAndroid Build Coastguard WorkerNote that message also may not have been serialized if it came from within the
270*635a8641SAndroid Build Coastguard Workersame process, in which case it may have no attached data and
271*635a8641SAndroid Build Coastguard Worker`MojoGetMessageData` will return `MOJO_RESULT_FAILED_PRECONDITION`. The
272*635a8641SAndroid Build Coastguard Workermessage's unserialized context can instead be retrieved using
273*635a8641SAndroid Build Coastguard Worker`MojoGetMessageContext`.
274*635a8641SAndroid Build Coastguard Worker
275*635a8641SAndroid Build Coastguard WorkerMessages read from a message pipe are owned by the caller and must be
276*635a8641SAndroid Build Coastguard Workersubsequently destroyed using `MojoDestroyMessage` (or, in theory, written to
277*635a8641SAndroid Build Coastguard Workeranother pipe using `MojoWriteMessage`.)
278*635a8641SAndroid Build Coastguard Worker
279*635a8641SAndroid Build Coastguard Worker### Messages With Handles
280*635a8641SAndroid Build Coastguard Worker
281*635a8641SAndroid Build Coastguard WorkerProbably the most useful feature of Mojo IPC is that message pipes can carry
282*635a8641SAndroid Build Coastguard Workerarbitrary Mojo handles, including other message pipes. This is also
283*635a8641SAndroid Build Coastguard Workerstraightforward.
284*635a8641SAndroid Build Coastguard Worker
285*635a8641SAndroid Build Coastguard WorkerHere's an example which creates two pipes, using the first pipe to transfer
286*635a8641SAndroid Build Coastguard Workerone end of the second pipe. If you have a good imagination you can pretend the
287*635a8641SAndroid Build Coastguard Workerfirst pipe spans a process boundary, which makes the example more practically
288*635a8641SAndroid Build Coastguard Workerinteresting:
289*635a8641SAndroid Build Coastguard Worker
290*635a8641SAndroid Build Coastguard Worker``` c
291*635a8641SAndroid Build Coastguard WorkerMojoHandle a, b;
292*635a8641SAndroid Build Coastguard WorkerMojoHandle c, d;
293*635a8641SAndroid Build Coastguard WorkerMojoCreateMessagePipe(NULL, &a, &b);
294*635a8641SAndroid Build Coastguard WorkerMojoCreateMessagePipe(NULL, &c, &d);
295*635a8641SAndroid Build Coastguard Worker
296*635a8641SAndroid Build Coastguard Worker// Allocate a message with an empty payload and handle |c| attached. Note that
297*635a8641SAndroid Build Coastguard Worker// this takes ownership of |c|, effectively invalidating its handle value.
298*635a8641SAndroid Build Coastguard WorkerMojoMessageHandle message;
299*635a8641SAndroid Build Coastguard Workervoid* buffer;
300*635a8641SAndroid Build Coastguard Workeruint32_t buffer_size;
301*635a8641SAndroid Build Coastguard WorkerMojoCreateMessage(nullptr, &message);
302*635a8641SAndroid Build Coastguard Worker
303*635a8641SAndroid Build Coastguard WorkerMojoAppendMessageDataOptions options;
304*635a8641SAndroid Build Coastguard Workeroptions.struct_size = sizeof(options);
305*635a8641SAndroid Build Coastguard Workeroptions.flags = MOJO_APPEND_MESSAGE_DATA_FLAG_COMMIT_SIZE;
306*635a8641SAndroid Build Coastguard WorkerMojoAppendMessageData(message, &options, 2, &c, 1, &buffer, &buffer_size);
307*635a8641SAndroid Build Coastguard Workermemcpy(buffer, "hi", 2);
308*635a8641SAndroid Build Coastguard WorkerMojoWriteMessage(a, message, nullptr);
309*635a8641SAndroid Build Coastguard Worker
310*635a8641SAndroid Build Coastguard Worker// Some time later...
311*635a8641SAndroid Build Coastguard WorkerMojoHandle e;
312*635a8641SAndroid Build Coastguard Workeruint32_t num_handles = 1;
313*635a8641SAndroid Build Coastguard WorkerMojoReadMessage(b, nullptr, &message);
314*635a8641SAndroid Build Coastguard WorkerMojoGetMessageData(message, nullptr, &buffer, &buffer_size, &e, &num_handles);
315*635a8641SAndroid Build Coastguard Worker```
316*635a8641SAndroid Build Coastguard Worker
317*635a8641SAndroid Build Coastguard WorkerAt this point the handle in `e` is now referencing the same message pipe
318*635a8641SAndroid Build Coastguard Workerendpoint which was originally referenced by `c`.
319*635a8641SAndroid Build Coastguard Worker
320*635a8641SAndroid Build Coastguard WorkerNote that `num_handles` above is initialized to 1 before we pass its address to
321*635a8641SAndroid Build Coastguard Worker`MojoGetMessageData`. This is to indicate how much `MojoHandle` storage is
322*635a8641SAndroid Build Coastguard Workeravailable at the output buffer we gave it (`&e` above).
323*635a8641SAndroid Build Coastguard Worker
324*635a8641SAndroid Build Coastguard WorkerIf we didn't know how many handles to expect in an incoming message -- which is
325*635a8641SAndroid Build Coastguard Workeroften the case -- we can use `MojoGetMessageData` to query for this information
326*635a8641SAndroid Build Coastguard Workerfirst:
327*635a8641SAndroid Build Coastguard Worker
328*635a8641SAndroid Build Coastguard Worker``` c
329*635a8641SAndroid Build Coastguard WorkerMojoMessageHandle message;
330*635a8641SAndroid Build Coastguard Workervoid* buffer;
331*635a8641SAndroid Build Coastguard Workeruint32_t num_bytes = 0;
332*635a8641SAndroid Build Coastguard Workeruint32_t num_handles = 0;
333*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoGetMessageData(message, nullptr, &buffer, &num_bytes,
334*635a8641SAndroid Build Coastguard Worker                                       nullptr, &num_handles);
335*635a8641SAndroid Build Coastguard Worker```
336*635a8641SAndroid Build Coastguard Worker
337*635a8641SAndroid Build Coastguard WorkerIf `message` has some non-zero number of handles, `result` will be
338*635a8641SAndroid Build Coastguard Worker`MOJO_RESULT_RESOURCE_EXHAUSTED`, and both `num_bytes` and `num_handles` will be
339*635a8641SAndroid Build Coastguard Workerupdated to reflect the payload size and number of attached handles in the
340*635a8641SAndroid Build Coastguard Workermessage.
341*635a8641SAndroid Build Coastguard Worker
342*635a8641SAndroid Build Coastguard Worker## Data Pipes
343*635a8641SAndroid Build Coastguard Worker
344*635a8641SAndroid Build Coastguard WorkerData pipes provide an efficient unidirectional channel for moving large amounts
345*635a8641SAndroid Build Coastguard Workerof unframed data between two endpoints. Every data pipe has a fixed
346*635a8641SAndroid Build Coastguard Worker**element size** and **capacity**. Reads and writes must be done in sizes that
347*635a8641SAndroid Build Coastguard Workerare a multiple of the element size, and writes to the pipe can only be queued
348*635a8641SAndroid Build Coastguard Workerup to the pipe's capacity before reads must be done to make more space
349*635a8641SAndroid Build Coastguard Workeravailable.
350*635a8641SAndroid Build Coastguard Worker
351*635a8641SAndroid Build Coastguard WorkerEvery data pipe has a single **producer** handle used to write data into the
352*635a8641SAndroid Build Coastguard Workerpipe and a single **consumer** handle used to read data out of the pipe.
353*635a8641SAndroid Build Coastguard Worker
354*635a8641SAndroid Build Coastguard WorkerFinally, data pipes support both immediate I/O -- reading into and writing out
355*635a8641SAndroid Build Coastguard Workerfrom user-supplied buffers -- as well as two-phase I/O, allowing callers to
356*635a8641SAndroid Build Coastguard Workertemporarily lock some portion of the data pipe in order to read or write its
357*635a8641SAndroid Build Coastguard Workercontents directly.
358*635a8641SAndroid Build Coastguard Worker
359*635a8641SAndroid Build Coastguard WorkerSee [//mojo/public/c/system/data_pipe.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/data_pipe.h)
360*635a8641SAndroid Build Coastguard Workerfor detailed data pipe API documentation.
361*635a8641SAndroid Build Coastguard Worker
362*635a8641SAndroid Build Coastguard Worker### Creating Data Pipes
363*635a8641SAndroid Build Coastguard Worker
364*635a8641SAndroid Build Coastguard WorkerUse `MojoCreateDataPipe` to create a new data pipe. The
365*635a8641SAndroid Build Coastguard Worker`MojoCreateDataPipeOptions` structure is used to configure the new pipe, but
366*635a8641SAndroid Build Coastguard Workerthis can be omitted to assume the default options of a single-byte element size
367*635a8641SAndroid Build Coastguard Workerand an implementation-defined default capacity (64 kB at the time of this
368*635a8641SAndroid Build Coastguard Workerwriting.)
369*635a8641SAndroid Build Coastguard Worker
370*635a8641SAndroid Build Coastguard Worker``` c
371*635a8641SAndroid Build Coastguard WorkerMojoHandle producer, consumer;
372*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoCreateDataPipe(NULL, &producer, &consumer);
373*635a8641SAndroid Build Coastguard Worker```
374*635a8641SAndroid Build Coastguard Worker
375*635a8641SAndroid Build Coastguard Worker### Immediate I/O
376*635a8641SAndroid Build Coastguard Worker
377*635a8641SAndroid Build Coastguard WorkerData can be written into or read out of a data pipe using buffers provided by
378*635a8641SAndroid Build Coastguard Workerthe caller. This is generally more convenient than two-phase I/O but is
379*635a8641SAndroid Build Coastguard Workeralso less efficient due to extra copying.
380*635a8641SAndroid Build Coastguard Worker
381*635a8641SAndroid Build Coastguard Worker``` c
382*635a8641SAndroid Build Coastguard Workeruint32_t num_bytes = 12;
383*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoWriteData(producer, "datadatadata", &num_bytes,
384*635a8641SAndroid Build Coastguard Worker                                  nullptr);
385*635a8641SAndroid Build Coastguard Worker```
386*635a8641SAndroid Build Coastguard Worker
387*635a8641SAndroid Build Coastguard WorkerThe above snippet will attempt to write 12 bytes into the data pipe, which
388*635a8641SAndroid Build Coastguard Workershould succeed and return `MOJO_RESULT_OK`. If the available capacity on the
389*635a8641SAndroid Build Coastguard Workerpipe was less than the amount requested (the input value of `*num_bytes`) this
390*635a8641SAndroid Build Coastguard Workerwill copy what it can into the pipe and return the number of bytes written in
391*635a8641SAndroid Build Coastguard Worker`*num_bytes`. If no data could be copied this will instead return
392*635a8641SAndroid Build Coastguard Worker`MOJO_RESULT_SHOULD_WAIT`.
393*635a8641SAndroid Build Coastguard Worker
394*635a8641SAndroid Build Coastguard WorkerReading from the consumer is a similar operation.
395*635a8641SAndroid Build Coastguard Worker
396*635a8641SAndroid Build Coastguard Worker``` c
397*635a8641SAndroid Build Coastguard Workerchar buffer[64];
398*635a8641SAndroid Build Coastguard Workeruint32_t num_bytes = 64;
399*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoReadData(consumer, nullptr, buffer, &num_bytes);
400*635a8641SAndroid Build Coastguard Worker```
401*635a8641SAndroid Build Coastguard Worker
402*635a8641SAndroid Build Coastguard WorkerThis will attempt to read up to 64 bytes, returning the actual number of bytes
403*635a8641SAndroid Build Coastguard Workerread in `*num_bytes`.
404*635a8641SAndroid Build Coastguard Worker
405*635a8641SAndroid Build Coastguard Worker`MojoReadData` supports a number of interesting flags to change the behavior:
406*635a8641SAndroid Build Coastguard Workeryou can peek at the data (copy bytes out without removing them from the pipe),
407*635a8641SAndroid Build Coastguard Workerquery the number of bytes available without doing any actual reading of the
408*635a8641SAndroid Build Coastguard Workercontents, or discard data from the pipe without bothering to copy it anywhere.
409*635a8641SAndroid Build Coastguard Worker
410*635a8641SAndroid Build Coastguard WorkerThis also supports a `MOJO_READ_DATA_FLAG_ALL_OR_NONE` which ensures that the
411*635a8641SAndroid Build Coastguard Workercall succeeds **only** if the exact number of bytes requested could be read.
412*635a8641SAndroid Build Coastguard WorkerOtherwise such a request will fail with `MOJO_READ_DATA_OUT_OF_RANGE`.
413*635a8641SAndroid Build Coastguard Worker
414*635a8641SAndroid Build Coastguard Worker### Two-Phase I/O
415*635a8641SAndroid Build Coastguard Worker
416*635a8641SAndroid Build Coastguard WorkerData pipes also support two-phase I/O operations, allowing a caller to
417*635a8641SAndroid Build Coastguard Workertemporarily lock a portion of the data pipe's storage for direct memory access.
418*635a8641SAndroid Build Coastguard Worker
419*635a8641SAndroid Build Coastguard Worker``` c
420*635a8641SAndroid Build Coastguard Workervoid* buffer;
421*635a8641SAndroid Build Coastguard Workeruint32_t num_bytes = 1024;
422*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoBeginWriteData(producer, nullptr, &buffer, &num_bytes);
423*635a8641SAndroid Build Coastguard Worker```
424*635a8641SAndroid Build Coastguard Worker
425*635a8641SAndroid Build Coastguard WorkerThis requests write access to a region of up to 1024 bytes of the data pipe's
426*635a8641SAndroid Build Coastguard Workernext available capacity. Upon success, `buffer` will point to the writable
427*635a8641SAndroid Build Coastguard Workerstorage and `num_bytes` will indicate the size of the buffer there.
428*635a8641SAndroid Build Coastguard Worker
429*635a8641SAndroid Build Coastguard WorkerThe caller should then write some data into the memory region and release it
430*635a8641SAndroid Build Coastguard WorkerASAP, indicating the number of bytes actually written:
431*635a8641SAndroid Build Coastguard Worker
432*635a8641SAndroid Build Coastguard Worker``` c
433*635a8641SAndroid Build Coastguard Workermemcpy(buffer, "hello", 6);
434*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoEndWriteData(producer, 6, nullptr);
435*635a8641SAndroid Build Coastguard Worker```
436*635a8641SAndroid Build Coastguard Worker
437*635a8641SAndroid Build Coastguard WorkerTwo-phase reads look similar:
438*635a8641SAndroid Build Coastguard Worker
439*635a8641SAndroid Build Coastguard Worker``` c
440*635a8641SAndroid Build Coastguard Workervoid* buffer;
441*635a8641SAndroid Build Coastguard Workeruint32_t num_bytes = 1024;
442*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoBeginReadData(consumer, nullptr, &buffer, &num_bytes);
443*635a8641SAndroid Build Coastguard Worker// result should be MOJO_RESULT_OK, since there is some data available.
444*635a8641SAndroid Build Coastguard Worker
445*635a8641SAndroid Build Coastguard Workerprintf("Pipe says: %s", (const char*)buffer);  // Should say "hello".
446*635a8641SAndroid Build Coastguard Worker
447*635a8641SAndroid Build Coastguard Worker// Say we only consumed one byte.
448*635a8641SAndroid Build Coastguard Workerresult = MojoEndReadData(consumer, 1, nullptr);
449*635a8641SAndroid Build Coastguard Worker
450*635a8641SAndroid Build Coastguard Workernum_bytes = 1024;
451*635a8641SAndroid Build Coastguard Workerresult = MojoBeginReadData(consumer, nullptr, &buffer, &num_bytes);
452*635a8641SAndroid Build Coastguard Workerprintf("Pipe says: %s", (const char*)buffer);  // Should say "ello".
453*635a8641SAndroid Build Coastguard Workerresult = MojoEndReadData(consumer, 5, nullptr);
454*635a8641SAndroid Build Coastguard Worker```
455*635a8641SAndroid Build Coastguard Worker
456*635a8641SAndroid Build Coastguard Worker## Shared Buffers
457*635a8641SAndroid Build Coastguard Worker
458*635a8641SAndroid Build Coastguard WorkerShared buffers are chunks of memory which can be mapped simultaneously by
459*635a8641SAndroid Build Coastguard Workermultiple processes. Mojo provides a simple API to make these available to
460*635a8641SAndroid Build Coastguard Workerapplications.
461*635a8641SAndroid Build Coastguard Worker
462*635a8641SAndroid Build Coastguard WorkerSee [//mojo/public/c/system/buffer.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/buffer.h)
463*635a8641SAndroid Build Coastguard Workerfor detailed shared buffer API documentation.
464*635a8641SAndroid Build Coastguard Worker
465*635a8641SAndroid Build Coastguard Worker### Creating Buffer Handles
466*635a8641SAndroid Build Coastguard Worker
467*635a8641SAndroid Build Coastguard WorkerUsage is straightforward. You can create a new buffer:
468*635a8641SAndroid Build Coastguard Worker
469*635a8641SAndroid Build Coastguard Worker``` c
470*635a8641SAndroid Build Coastguard Worker// Allocate a shared buffer of 4 kB.
471*635a8641SAndroid Build Coastguard WorkerMojoHandle buffer;
472*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoCreateSharedBuffer(4096, NULL, &buffer);
473*635a8641SAndroid Build Coastguard Worker```
474*635a8641SAndroid Build Coastguard Worker
475*635a8641SAndroid Build Coastguard WorkerYou can also duplicate an existing shared buffer handle:
476*635a8641SAndroid Build Coastguard Worker
477*635a8641SAndroid Build Coastguard Worker``` c
478*635a8641SAndroid Build Coastguard WorkerMojoHandle another_name_for_buffer;
479*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoDuplicateBufferHandle(buffer, NULL,
480*635a8641SAndroid Build Coastguard Worker                                              &another_name_for_buffer);
481*635a8641SAndroid Build Coastguard Worker```
482*635a8641SAndroid Build Coastguard Worker
483*635a8641SAndroid Build Coastguard WorkerThis is useful if you want to retain a handle to the buffer while also sharing
484*635a8641SAndroid Build Coastguard Workerhandles with one or more other clients. The allocated buffer remains valid as
485*635a8641SAndroid Build Coastguard Workerlong as at least one shared buffer handle exists to reference it.
486*635a8641SAndroid Build Coastguard Worker
487*635a8641SAndroid Build Coastguard Worker### Mapping Buffers
488*635a8641SAndroid Build Coastguard Worker
489*635a8641SAndroid Build Coastguard WorkerYou can map (and later unmap) a specified range of the buffer to get direct
490*635a8641SAndroid Build Coastguard Workermemory access to its contents:
491*635a8641SAndroid Build Coastguard Worker
492*635a8641SAndroid Build Coastguard Worker``` c
493*635a8641SAndroid Build Coastguard Workervoid* data;
494*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoMapBuffer(buffer, 0, 64, nullptr, &data);
495*635a8641SAndroid Build Coastguard Worker
496*635a8641SAndroid Build Coastguard Worker*(int*)data = 42;
497*635a8641SAndroid Build Coastguard Workerresult = MojoUnmapBuffer(data);
498*635a8641SAndroid Build Coastguard Worker```
499*635a8641SAndroid Build Coastguard Worker
500*635a8641SAndroid Build Coastguard WorkerA buffer may have any number of active mappings at a time, in any number of
501*635a8641SAndroid Build Coastguard Workerprocesses.
502*635a8641SAndroid Build Coastguard Worker
503*635a8641SAndroid Build Coastguard Worker### Read-Only Handles
504*635a8641SAndroid Build Coastguard Worker
505*635a8641SAndroid Build Coastguard WorkerAn option can also be specified on `MojoDuplicateBufferHandle` to ensure
506*635a8641SAndroid Build Coastguard Workerthat the newly duplicated handle can only be mapped to read-only memory:
507*635a8641SAndroid Build Coastguard Worker
508*635a8641SAndroid Build Coastguard Worker``` c
509*635a8641SAndroid Build Coastguard WorkerMojoHandle read_only_buffer;
510*635a8641SAndroid Build Coastguard WorkerMojoDuplicateBufferHandleOptions options;
511*635a8641SAndroid Build Coastguard Workeroptions.struct_size = sizeof(options);
512*635a8641SAndroid Build Coastguard Workeroptions.flags = MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_READ_ONLY;
513*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoDuplicateBufferHandle(buffer, &options,
514*635a8641SAndroid Build Coastguard Worker                                              &read_only_buffer);
515*635a8641SAndroid Build Coastguard Worker
516*635a8641SAndroid Build Coastguard Worker// Attempt to map and write to the buffer using the read-only handle:
517*635a8641SAndroid Build Coastguard Workervoid* data;
518*635a8641SAndroid Build Coastguard Workerresult = MojoMapBuffer(read_only_buffer, 0, 64, nullptr, &data);
519*635a8641SAndroid Build Coastguard Worker*(int*)data = 42;  // CRASH
520*635a8641SAndroid Build Coastguard Worker```
521*635a8641SAndroid Build Coastguard Worker
522*635a8641SAndroid Build Coastguard Worker*** note
523*635a8641SAndroid Build Coastguard Worker**NOTE:** One important limitation of the current implementation is that
524*635a8641SAndroid Build Coastguard Workerread-only handles can only be produced from a handle that was originally created
525*635a8641SAndroid Build Coastguard Workerby `MojoCreateSharedBuffer` (*i.e.*, you cannot create a read-only duplicate
526*635a8641SAndroid Build Coastguard Workerfrom a non-read-only duplicate), and the handle cannot have been transferred
527*635a8641SAndroid Build Coastguard Workerover a message pipe first.
528*635a8641SAndroid Build Coastguard Worker***
529*635a8641SAndroid Build Coastguard Worker
530*635a8641SAndroid Build Coastguard Worker## Native Platform Handles (File Descriptors, Windows Handles, *etc.*)
531*635a8641SAndroid Build Coastguard Worker
532*635a8641SAndroid Build Coastguard WorkerNative platform handles to system objects can be wrapped as Mojo handles for
533*635a8641SAndroid Build Coastguard Workerseamless transit over message pipes. Mojo currently supports wrapping POSIX
534*635a8641SAndroid Build Coastguard Workerfile descriptors, Windows handles, Mach ports, and Fuchsia zx_handles.
535*635a8641SAndroid Build Coastguard Worker
536*635a8641SAndroid Build Coastguard WorkerSee [//mojo/public/c/system/platform_handle.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/platform_handle.h)
537*635a8641SAndroid Build Coastguard Workerfor detailed platform handle API documentation.
538*635a8641SAndroid Build Coastguard Worker
539*635a8641SAndroid Build Coastguard Worker### Wrapping Basic Handle Types
540*635a8641SAndroid Build Coastguard Worker
541*635a8641SAndroid Build Coastguard WorkerWrapping a POSIX file descriptor is simple:
542*635a8641SAndroid Build Coastguard Worker
543*635a8641SAndroid Build Coastguard Worker``` c
544*635a8641SAndroid Build Coastguard WorkerMojoPlatformHandle platform_handle;
545*635a8641SAndroid Build Coastguard Workerplatform_handle.struct_size = sizeof(platform_handle);
546*635a8641SAndroid Build Coastguard Workerplatform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
547*635a8641SAndroid Build Coastguard Workerplatform_handle.value = (uint64_t)fd;
548*635a8641SAndroid Build Coastguard WorkerMojoHandle handle;
549*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoWrapPlatformHandle(&platform_handle, nullptr, &handle);
550*635a8641SAndroid Build Coastguard Worker```
551*635a8641SAndroid Build Coastguard Worker
552*635a8641SAndroid Build Coastguard WorkerNote that at this point `handle` effectively owns the file descriptor
553*635a8641SAndroid Build Coastguard Workerand if you were to call `MojoClose(handle)`, the file descriptor would be closed
554*635a8641SAndroid Build Coastguard Workertoo; but we're not going to close it here! We're going to pretend we've sent it
555*635a8641SAndroid Build Coastguard Workerover a message pipe, and now we want to unwrap it on the other side:
556*635a8641SAndroid Build Coastguard Worker
557*635a8641SAndroid Build Coastguard Worker``` c
558*635a8641SAndroid Build Coastguard WorkerMojoPlatformHandle platform_handle;
559*635a8641SAndroid Build Coastguard Workerplatform_handle.struct_size = sizeof(platform_handle);
560*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoUnwrapPlatformHandle(handle, nullptr, &platform_handle);
561*635a8641SAndroid Build Coastguard Workerint fd = (int)platform_handle.value;
562*635a8641SAndroid Build Coastguard Worker```
563*635a8641SAndroid Build Coastguard Worker
564*635a8641SAndroid Build Coastguard WorkerThe situation looks nearly identical for wrapping and unwrapping Windows handles
565*635a8641SAndroid Build Coastguard Workerand Mach ports.
566*635a8641SAndroid Build Coastguard Worker
567*635a8641SAndroid Build Coastguard Worker### Wrapping Shared Buffer Handles
568*635a8641SAndroid Build Coastguard Worker
569*635a8641SAndroid Build Coastguard WorkerUnlike other handle types, shared buffers have special meaning in Mojo, and it
570*635a8641SAndroid Build Coastguard Workermay be desirable to wrap a native platform handle -- along with some extra
571*635a8641SAndroid Build Coastguard Workermetadata -- such that be treated like a real Mojo shared buffer handle.
572*635a8641SAndroid Build Coastguard WorkerConversely it can also be useful to unpack a Mojo shared buffer handle into
573*635a8641SAndroid Build Coastguard Workera native platform handle which references the buffer object. Both of these
574*635a8641SAndroid Build Coastguard Workerthings can be done using the `MojoWrapPlatformSharedBuffer` and
575*635a8641SAndroid Build Coastguard Worker`MojoUnwrapPlatformSharedBuffer` APIs.
576*635a8641SAndroid Build Coastguard Worker
577*635a8641SAndroid Build Coastguard WorkerOn Windows, the wrapped platform handle must always be a Windows handle to
578*635a8641SAndroid Build Coastguard Workera file mapping object.
579*635a8641SAndroid Build Coastguard Worker
580*635a8641SAndroid Build Coastguard WorkerOn OS X, the wrapped platform handle must be a memory-object send right.
581*635a8641SAndroid Build Coastguard Worker
582*635a8641SAndroid Build Coastguard WorkerOn all other POSIX systems, the wrapped platform handle must be a file
583*635a8641SAndroid Build Coastguard Workerdescriptor for a shared memory object.
584*635a8641SAndroid Build Coastguard Worker
585*635a8641SAndroid Build Coastguard Worker## Signals & Traps
586*635a8641SAndroid Build Coastguard Worker
587*635a8641SAndroid Build Coastguard WorkerMessage pipe and data pipe (producer and consumer) handles can change state in
588*635a8641SAndroid Build Coastguard Workerways that may be interesting to a Mojo API user. For example, you may wish to
589*635a8641SAndroid Build Coastguard Workerknow when a message pipe handle has messages available to be read or when its
590*635a8641SAndroid Build Coastguard Workerpeer has been closed. Such states are reflected by a fixed set of boolean
591*635a8641SAndroid Build Coastguard Workersignals on each pipe handle.
592*635a8641SAndroid Build Coastguard Worker
593*635a8641SAndroid Build Coastguard Worker### Signals
594*635a8641SAndroid Build Coastguard Worker
595*635a8641SAndroid Build Coastguard WorkerEvery message pipe and data pipe handle maintains a notion of
596*635a8641SAndroid Build Coastguard Worker**signaling state** which may be queried at any time. For example:
597*635a8641SAndroid Build Coastguard Worker
598*635a8641SAndroid Build Coastguard Worker``` c
599*635a8641SAndroid Build Coastguard WorkerMojoHandle a, b;
600*635a8641SAndroid Build Coastguard WorkerMojoCreateMessagePipe(NULL, &a, &b);
601*635a8641SAndroid Build Coastguard Worker
602*635a8641SAndroid Build Coastguard WorkerMojoHandleSignalsState state;
603*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoQueryHandleSignalsState(a, &state);
604*635a8641SAndroid Build Coastguard Worker```
605*635a8641SAndroid Build Coastguard Worker
606*635a8641SAndroid Build Coastguard WorkerThe `MojoHandleSignalsState` structure exposes two fields: `satisfied_signals`
607*635a8641SAndroid Build Coastguard Workerand `satisfiable_signals`. Both of these are bitmasks of the type
608*635a8641SAndroid Build Coastguard Worker`MojoHandleSignals` (see [//mojo/public/c/system/types.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/types.h)
609*635a8641SAndroid Build Coastguard Workerfor more details.)
610*635a8641SAndroid Build Coastguard Worker
611*635a8641SAndroid Build Coastguard WorkerThe `satisfied_signals` bitmask indicates signals which were satisfied on the
612*635a8641SAndroid Build Coastguard Workerhandle at the time of the call, while the `satisfiable_signals` bitmask
613*635a8641SAndroid Build Coastguard Workerindicates signals which were still possible to satisfy at the time of the call.
614*635a8641SAndroid Build Coastguard WorkerIt is thus by definition always true that:
615*635a8641SAndroid Build Coastguard Worker
616*635a8641SAndroid Build Coastguard Worker``` c
617*635a8641SAndroid Build Coastguard Worker(satisfied_signals | satisfiable_signals) == satisfiable_signals
618*635a8641SAndroid Build Coastguard Worker```
619*635a8641SAndroid Build Coastguard Worker
620*635a8641SAndroid Build Coastguard WorkerIn other words a signal obviously cannot be satisfied if it is no longer
621*635a8641SAndroid Build Coastguard Workersatisfiable. Furthermore once a signal is unsatisfiable, *i.e.* is no longer
622*635a8641SAndroid Build Coastguard Workerset in `sastisfiable_signals`, it can **never** become satisfiable again.
623*635a8641SAndroid Build Coastguard Worker
624*635a8641SAndroid Build Coastguard WorkerTo illustrate this more clearly, consider the message pipe created above. Both
625*635a8641SAndroid Build Coastguard Workerends of the pipe are still open and neither has been written to yet. Thus both
626*635a8641SAndroid Build Coastguard Workerhandles start out with the same signaling state:
627*635a8641SAndroid Build Coastguard Worker
628*635a8641SAndroid Build Coastguard Worker| Field                 | State |
629*635a8641SAndroid Build Coastguard Worker|-----------------------|-------|
630*635a8641SAndroid Build Coastguard Worker| `satisfied_signals`   | `MOJO_HANDLE_SIGNAL_WRITABLE`
631*635a8641SAndroid Build Coastguard Worker| `satisfiable_signals` | `MOJO_HANDLE_SIGNAL_READABLE + MOJO_HANDLE_SIGNAL_WRITABLE + MOJO_HANDLE_SIGNAL_PEER_CLOSED`
632*635a8641SAndroid Build Coastguard Worker
633*635a8641SAndroid Build Coastguard WorkerWriting a message to handle `b` will eventually alter the signaling state of `a`
634*635a8641SAndroid Build Coastguard Workersuch that `MOJO_HANDLE_SIGNAL_READABLE` also becomes satisfied. If we were to
635*635a8641SAndroid Build Coastguard Workerthen close `b`, the signaling state of `a` would look like:
636*635a8641SAndroid Build Coastguard Worker
637*635a8641SAndroid Build Coastguard Worker| Field                 | State |
638*635a8641SAndroid Build Coastguard Worker|-----------------------|-------|
639*635a8641SAndroid Build Coastguard Worker| `satisfied_signals`   | `MOJO_HANDLE_SIGNAL_READABLE + MOJO_HANDLE_SIGNAL_PEER_CLOSED`
640*635a8641SAndroid Build Coastguard Worker| `satisfiable_signals` | `MOJO_HANDLE_SIGNAL_READABLE + MOJO_HANDLE_SIGNAL_PEER_CLOSED`
641*635a8641SAndroid Build Coastguard Worker
642*635a8641SAndroid Build Coastguard WorkerNote that even though `a`'s peer is known to be closed (hence making `a`
643*635a8641SAndroid Build Coastguard Workerpermanently unwritable) it remains readable because there's still an unread
644*635a8641SAndroid Build Coastguard Workerreceived message waiting to be read from `a`.
645*635a8641SAndroid Build Coastguard Worker
646*635a8641SAndroid Build Coastguard WorkerFinally if we read the last message from `a` its signaling state becomes:
647*635a8641SAndroid Build Coastguard Worker
648*635a8641SAndroid Build Coastguard Worker| Field                 | State |
649*635a8641SAndroid Build Coastguard Worker|-----------------------|-------|
650*635a8641SAndroid Build Coastguard Worker| `satisfied_signals`   | `MOJO_HANDLE_SIGNAL_PEER_CLOSED`
651*635a8641SAndroid Build Coastguard Worker| `satisfiable_signals` | `MOJO_HANDLE_SIGNAL_PEER_CLOSED`
652*635a8641SAndroid Build Coastguard Worker
653*635a8641SAndroid Build Coastguard Workerand we know definitively that `a` can never be read from again.
654*635a8641SAndroid Build Coastguard Worker
655*635a8641SAndroid Build Coastguard Worker### Trapping Signals
656*635a8641SAndroid Build Coastguard Worker
657*635a8641SAndroid Build Coastguard WorkerThe ability to query a handle's signaling state can be useful, but it's not
658*635a8641SAndroid Build Coastguard Workersufficient to support robust and efficient pipe usage. Mojo traps empower users
659*635a8641SAndroid Build Coastguard Workerwith the ability to **trap** changes in a handle's signaling state and
660*635a8641SAndroid Build Coastguard Workerautomatically invoke a notification handler in response.
661*635a8641SAndroid Build Coastguard Worker
662*635a8641SAndroid Build Coastguard WorkerWhen a trap is created it must be bound to a function pointer matching
663*635a8641SAndroid Build Coastguard Workerthe following signature, defined in
664*635a8641SAndroid Build Coastguard Worker[//mojo/public/c/system/trap.h](https://cs.chromium.org/chromium/src/mojo/public/c/system/trap.h):
665*635a8641SAndroid Build Coastguard Worker
666*635a8641SAndroid Build Coastguard Worker``` c
667*635a8641SAndroid Build Coastguard Workertypedef void (*MojoTrapEventHandler)(const struct MojoTrapEvent* event);
668*635a8641SAndroid Build Coastguard Worker```
669*635a8641SAndroid Build Coastguard Worker
670*635a8641SAndroid Build Coastguard WorkerThe `event` parameter conveys details about why the event handler is being
671*635a8641SAndroid Build Coastguard Workerinvoked. The handler may be called **at any time** and **from any thread**, so
672*635a8641SAndroid Build Coastguard Workerit is critical that handler implementations account for this.
673*635a8641SAndroid Build Coastguard Worker
674*635a8641SAndroid Build Coastguard WorkerIt's also helpful to understand a bit about the mechanism by which the handler
675*635a8641SAndroid Build Coastguard Workercan be invoked. Essentially, any Mojo C System API call may elicit a handle
676*635a8641SAndroid Build Coastguard Workerstate change of some kind. If such a change is relevant to conditions watched by
677*635a8641SAndroid Build Coastguard Workera trap, and that trap is in a state which allows it raise a corresponding
678*635a8641SAndroid Build Coastguard Workernotification, its notification handler will be invoked synchronously some time
679*635a8641SAndroid Build Coastguard Workerbefore the stack unwinds beyond the outermost System API call on the current
680*635a8641SAndroid Build Coastguard Workerthread.
681*635a8641SAndroid Build Coastguard Worker
682*635a8641SAndroid Build Coastguard WorkerHandle state changes can also occur as a result of incoming IPC from an external
683*635a8641SAndroid Build Coastguard Workerprocess. If a pipe in the current process is connected to an endpoint in another
684*635a8641SAndroid Build Coastguard Workerprocess and the internal Mojo system receives an incoming message bound for the
685*635a8641SAndroid Build Coastguard Workerlocal endpoint, the arrival of that message may trigger a state change on the
686*635a8641SAndroid Build Coastguard Workerreceiving handle and may therefore invoke one or more traps' notification
687*635a8641SAndroid Build Coastguard Workerhandlers as a result.
688*635a8641SAndroid Build Coastguard Worker
689*635a8641SAndroid Build Coastguard WorkerThe `MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL` flag on the `flags` field of `event`
690*635a8641SAndroid Build Coastguard Workeris used to indicate whether the handler was invoked due to such an internal
691*635a8641SAndroid Build Coastguard Workersystem IPC event (if the flag is unset), or if it was invoked synchronously due
692*635a8641SAndroid Build Coastguard Workerto some local API call (if the flag is set.) This distinction can be useful to
693*635a8641SAndroid Build Coastguard Workermake in certain cases to *e.g.* avoid accidental reentrancy in user code.
694*635a8641SAndroid Build Coastguard Worker
695*635a8641SAndroid Build Coastguard Worker### Creating a Trap
696*635a8641SAndroid Build Coastguard Worker
697*635a8641SAndroid Build Coastguard WorkerCreating a trap is simple:
698*635a8641SAndroid Build Coastguard Worker
699*635a8641SAndroid Build Coastguard Worker``` c
700*635a8641SAndroid Build Coastguard Worker
701*635a8641SAndroid Build Coastguard Workervoid OnNotification(const struct MojoTrapEvent* event) {
702*635a8641SAndroid Build Coastguard Worker  // ...
703*635a8641SAndroid Build Coastguard Worker}
704*635a8641SAndroid Build Coastguard Worker
705*635a8641SAndroid Build Coastguard WorkerMojoHandle t;
706*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoCreateTrap(&OnNotification, NULL, &t);
707*635a8641SAndroid Build Coastguard Worker```
708*635a8641SAndroid Build Coastguard Worker
709*635a8641SAndroid Build Coastguard WorkerLike all other `MojoHandle` types, traps may be destroyed by closing them with
710*635a8641SAndroid Build Coastguard Worker`MojoClose`. Unlike most other `MojoHandle` types, trap handles are **not**
711*635a8641SAndroid Build Coastguard Workertransferrable across message pipes.
712*635a8641SAndroid Build Coastguard Worker
713*635a8641SAndroid Build Coastguard WorkerIn order for a trap to be useful, it has have at least one **trigger** attached
714*635a8641SAndroid Build Coastguard Workerto it.
715*635a8641SAndroid Build Coastguard Worker
716*635a8641SAndroid Build Coastguard Worker### Adding a Trigger to a Trap
717*635a8641SAndroid Build Coastguard Worker
718*635a8641SAndroid Build Coastguard WorkerAny given trap can watch any given (message or data pipe) handle for some set
719*635a8641SAndroid Build Coastguard Workerof signaling conditions. A handle may be watched simultaneously by multiple
720*635a8641SAndroid Build Coastguard Workertraps, and a single trap can watch multiple different handles simultaneously.
721*635a8641SAndroid Build Coastguard Worker
722*635a8641SAndroid Build Coastguard Worker``` c
723*635a8641SAndroid Build Coastguard WorkerMojoHandle a, b;
724*635a8641SAndroid Build Coastguard WorkerMojoCreateMessagePipe(NULL, &a, &b);
725*635a8641SAndroid Build Coastguard Worker
726*635a8641SAndroid Build Coastguard Worker// Watch handle |a| for readability.
727*635a8641SAndroid Build Coastguard Workerconst uintptr_t context = 1234;
728*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoAddTrigger(t, a, MOJO_HANDLE_SIGNAL_READABLE,
729*635a8641SAndroid Build Coastguard Worker                                   MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
730*635a8641SAndroid Build Coastguard Worker                                   context, NULL);
731*635a8641SAndroid Build Coastguard Worker```
732*635a8641SAndroid Build Coastguard Worker
733*635a8641SAndroid Build Coastguard WorkerWe've successfully instructed trap `t` to begin watching pipe handle `a` for
734*635a8641SAndroid Build Coastguard Workerreadability. However, our recently created trap is still in a **disarmed**
735*635a8641SAndroid Build Coastguard Workerstate, meaning that it will never fire a notification pertaining to this
736*635a8641SAndroid Build Coastguard Workertrigger. It must be **armed** before that can happen.
737*635a8641SAndroid Build Coastguard Worker
738*635a8641SAndroid Build Coastguard Worker### Arming a Trap
739*635a8641SAndroid Build Coastguard Worker
740*635a8641SAndroid Build Coastguard WorkerIn order for a trap to invoke its notification handler in response to a relevant
741*635a8641SAndroid Build Coastguard Workersignaling state change on a watched handle, it must first be armed. A trap may
742*635a8641SAndroid Build Coastguard Workeronly be armed if none of its attached triggers would elicit a notification
743*635a8641SAndroid Build Coastguard Workerimmediately once armed.
744*635a8641SAndroid Build Coastguard Worker
745*635a8641SAndroid Build Coastguard WorkerIn this case `a` is clearly not yet readable, so arming should succeed:
746*635a8641SAndroid Build Coastguard Worker
747*635a8641SAndroid Build Coastguard Worker``` c
748*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoArmTrap(t, NULL, NULL, NULL);
749*635a8641SAndroid Build Coastguard Worker```
750*635a8641SAndroid Build Coastguard Worker
751*635a8641SAndroid Build Coastguard WorkerNow we can write to `b` to make `a` readable:
752*635a8641SAndroid Build Coastguard Worker
753*635a8641SAndroid Build Coastguard Worker``` c
754*635a8641SAndroid Build Coastguard WorkerMojoMessageHandle m;
755*635a8641SAndroid Build Coastguard WorkerMojoCreateMessage(nullptr, &m);
756*635a8641SAndroid Build Coastguard WorkerMojoWriteMessage(b, m, nullptr);
757*635a8641SAndroid Build Coastguard Worker```
758*635a8641SAndroid Build Coastguard Worker
759*635a8641SAndroid Build Coastguard WorkerEventually -- and in practice possibly before `MojoWriteMessage` even
760*635a8641SAndroid Build Coastguard Workerreturns -- this will cause `OnNotification` to be invoked on the calling thread
761*635a8641SAndroid Build Coastguard Workerwith the `context` value (*i.e.* 1234) that was given when the trigger was added
762*635a8641SAndroid Build Coastguard Workerto the trap.
763*635a8641SAndroid Build Coastguard Worker
764*635a8641SAndroid Build Coastguard WorkerThe `result` field of the event will be `MOJO_RESULT_OK` to indicate that the
765*635a8641SAndroid Build Coastguard Workertrigger's condition has been met. If the handle's state had instead changed in
766*635a8641SAndroid Build Coastguard Workersuch a way that the trigger's condition could never be met again (*e.g.* if `b`
767*635a8641SAndroid Build Coastguard Workerwere instead closed), `result` would instead indicate
768*635a8641SAndroid Build Coastguard Worker`MOJO_RESULT_FAILED_PRECONDITION`.
769*635a8641SAndroid Build Coastguard Worker
770*635a8641SAndroid Build Coastguard Worker**NOTE:** Immediately before a trigger decides to invoke its event handler, it
771*635a8641SAndroid Build Coastguard Workerautomatically disarms itself to prevent another state change from eliciting
772*635a8641SAndroid Build Coastguard Workeranother notification. Therefore a trap must be repeatedly rearmed in order to
773*635a8641SAndroid Build Coastguard Workercontinue dispatching events.
774*635a8641SAndroid Build Coastguard Worker
775*635a8641SAndroid Build Coastguard WorkerAs noted above, arming a watcher may fail if any of its triggers would be
776*635a8641SAndroid Build Coastguard Workeractivated immediately.  In that case, the caller may provide buffers to
777*635a8641SAndroid Build Coastguard Worker`MojoArmTrap` to receive information about a subset of the triggers which caused
778*635a8641SAndroid Build Coastguard Workerit to fail:
779*635a8641SAndroid Build Coastguard Worker
780*635a8641SAndroid Build Coastguard Worker``` c
781*635a8641SAndroid Build Coastguard Worker// Provide some storage for information about triggers that would have been
782*635a8641SAndroid Build Coastguard Worker// activated immediately.
783*635a8641SAndroid Build Coastguard Workeruint32_t num_blocking_events = 2;
784*635a8641SAndroid Build Coastguard WorkerMojoTrapEvent blocking_events[2] = {{sizeof(MojoTrapEvent)},
785*635a8641SAndroid Build Coastguard Worker                                    {sizeof(MojoTrapEvent)}};
786*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoArmTrap(t, NULL, &num_blocking_events,
787*635a8641SAndroid Build Coastguard Worker                                &blocking_events);
788*635a8641SAndroid Build Coastguard Worker```
789*635a8641SAndroid Build Coastguard Worker
790*635a8641SAndroid Build Coastguard WorkerBecause `a` is still readable this operation will now fail with
791*635a8641SAndroid Build Coastguard Worker`MOJO_RESULT_FAILED_PRECONDITION`. The input value of `num_blocking_events`
792*635a8641SAndroid Build Coastguard Workerinforms `MojoArmTrap` that it may store information regarding up to 2 triggers
793*635a8641SAndroid Build Coastguard Workerwhich have prevented arming. In this case of course there is only one active
794*635a8641SAndroid Build Coastguard Workertrigger, so upon return we will see:
795*635a8641SAndroid Build Coastguard Worker
796*635a8641SAndroid Build Coastguard Worker* `num_blocking_events` is `1`.
797*635a8641SAndroid Build Coastguard Worker* `blocking_events[0].trigger_context` is `1234`.
798*635a8641SAndroid Build Coastguard Worker* `blocking_events[0].result` is `MOJO_RESULT_OK`
799*635a8641SAndroid Build Coastguard Worker* `blocking_events[0].signals_state` is the last known signaling state of handle
800*635a8641SAndroid Build Coastguard Worker  `a`.
801*635a8641SAndroid Build Coastguard Worker
802*635a8641SAndroid Build Coastguard WorkerIn other words the stored information mirrors what would have been the resulting
803*635a8641SAndroid Build Coastguard Workerevent structure if the trap were allowed to arm and then notify immediately.
804*635a8641SAndroid Build Coastguard Worker
805*635a8641SAndroid Build Coastguard Worker### Removing a Trigger
806*635a8641SAndroid Build Coastguard Worker
807*635a8641SAndroid Build Coastguard WorkerThere are three ways a trigger can be removed:
808*635a8641SAndroid Build Coastguard Worker
809*635a8641SAndroid Build Coastguard Worker* The handle being watched by the trigger is closed
810*635a8641SAndroid Build Coastguard Worker* The trap handle is closed, in which case all of its attached triggers are
811*635a8641SAndroid Build Coastguard Worker  implicitly removed.
812*635a8641SAndroid Build Coastguard Worker* `MojoRemoveTrigger` is called for a given `context`.
813*635a8641SAndroid Build Coastguard Worker
814*635a8641SAndroid Build Coastguard WorkerIn the above example this means any of the following operations will cancel the
815*635a8641SAndroid Build Coastguard Workerwatch on `a`:
816*635a8641SAndroid Build Coastguard Worker
817*635a8641SAndroid Build Coastguard Worker``` c
818*635a8641SAndroid Build Coastguard Worker// Close the watched handle...
819*635a8641SAndroid Build Coastguard WorkerMojoClose(a);
820*635a8641SAndroid Build Coastguard Worker
821*635a8641SAndroid Build Coastguard Worker// OR close the trap handle...
822*635a8641SAndroid Build Coastguard WorkerMojoClose(t);
823*635a8641SAndroid Build Coastguard Worker
824*635a8641SAndroid Build Coastguard Worker// OR explicitly remove it.
825*635a8641SAndroid Build Coastguard WorkerMojoResult result = MojoRemoveTrigger(t, 1234, NULL);
826*635a8641SAndroid Build Coastguard Worker```
827*635a8641SAndroid Build Coastguard Worker
828*635a8641SAndroid Build Coastguard WorkerIn every case the trap's event handler is invoked for the cancelled trigger(es)
829*635a8641SAndroid Build Coastguard Workerregardless of whether or not the trap was armed at the time. The event handler
830*635a8641SAndroid Build Coastguard Workerreceives a `result` of `MOJO_RESULT_CANCELLED` for each of these invocations,
831*635a8641SAndroid Build Coastguard Workerand this is guaranteed to be the final event for any given trigger context.
832*635a8641SAndroid Build Coastguard Worker
833*635a8641SAndroid Build Coastguard Worker### Practical Trigger Context Usage
834*635a8641SAndroid Build Coastguard Worker
835*635a8641SAndroid Build Coastguard WorkerIt is common and probably wise to treat a trigger's `context` value as an opaque
836*635a8641SAndroid Build Coastguard Workerpointer to some thread-safe state associated in some way with the handle being
837*635a8641SAndroid Build Coastguard Workerwatched. Here's a small example which uses a single trap to watch both ends of a
838*635a8641SAndroid Build Coastguard Workermessage pipe and accumulate a count of messages received at each end.
839*635a8641SAndroid Build Coastguard Worker
840*635a8641SAndroid Build Coastguard Worker``` c
841*635a8641SAndroid Build Coastguard Worker// NOTE: For the sake of simplicity this example code is not in fact
842*635a8641SAndroid Build Coastguard Worker// thread-safe. As long as there's only one thread running in the process and
843*635a8641SAndroid Build Coastguard Worker// no external process connections, this is fine.
844*635a8641SAndroid Build Coastguard Worker
845*635a8641SAndroid Build Coastguard Workerstruct WatchedHandleState {
846*635a8641SAndroid Build Coastguard Worker  MojoHandle trap;
847*635a8641SAndroid Build Coastguard Worker  MojoHandle handle;
848*635a8641SAndroid Build Coastguard Worker  int message_count;
849*635a8641SAndroid Build Coastguard Worker};
850*635a8641SAndroid Build Coastguard Worker
851*635a8641SAndroid Build Coastguard Workervoid OnNotification(const struct MojoTrapEvent* event) {
852*635a8641SAndroid Build Coastguard Worker  struct WatchedHandleState* state =
853*635a8641SAndroid Build Coastguard Worker      (struct WatchedHandleState*)(event->trigger_context);
854*635a8641SAndroid Build Coastguard Worker  MojoResult rv;
855*635a8641SAndroid Build Coastguard Worker
856*635a8641SAndroid Build Coastguard Worker  if (event->result == MOJO_RESULT_CANCELLED) {
857*635a8641SAndroid Build Coastguard Worker    // Cancellation is always the last event and is guaranteed to happen for
858*635a8641SAndroid Build Coastguard Worker    // every context, assuming no handles are leaked. We treat this as an
859*635a8641SAndroid Build Coastguard Worker    // opportunity to free the WatchedHandleState.
860*635a8641SAndroid Build Coastguard Worker    free(state);
861*635a8641SAndroid Build Coastguard Worker    return;
862*635a8641SAndroid Build Coastguard Worker  }
863*635a8641SAndroid Build Coastguard Worker
864*635a8641SAndroid Build Coastguard Worker  if (result == MOJO_RESULT_FAILED_PRECONDITION) {
865*635a8641SAndroid Build Coastguard Worker    // No longer readable, i.e. the other handle must have been closed. Better
866*635a8641SAndroid Build Coastguard Worker    // cancel. Note that we could also just call MojoClose(state->trap) here
867*635a8641SAndroid Build Coastguard Worker    // since we know there's only one attached trigger.
868*635a8641SAndroid Build Coastguard Worker    MojoRemoveTrigger(state->trap, event->trigger_context, NULL);
869*635a8641SAndroid Build Coastguard Worker    return;
870*635a8641SAndroid Build Coastguard Worker  }
871*635a8641SAndroid Build Coastguard Worker
872*635a8641SAndroid Build Coastguard Worker  // This is the only handle watched by the trap, so as long as we can't arm
873*635a8641SAndroid Build Coastguard Worker  // the watcher we know something's up with this handle. Try to read messages
874*635a8641SAndroid Build Coastguard Worker  // until we can successfully arm again or something goes terribly wrong.
875*635a8641SAndroid Build Coastguard Worker  while (MojoArmTrap(state->trap, NULL NULL, NULL) ==
876*635a8641SAndroid Build Coastguard Worker         MOJO_RESULT_FAILED_PRECONDITION) {
877*635a8641SAndroid Build Coastguard Worker    rv = MojoReadMessageNew(state->handle, NULL, NULL, NULL,
878*635a8641SAndroid Build Coastguard Worker                            MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
879*635a8641SAndroid Build Coastguard Worker    if (rv == MOJO_RESULT_OK) {
880*635a8641SAndroid Build Coastguard Worker      state->message_count++;
881*635a8641SAndroid Build Coastguard Worker    } else if (rv == MOJO_RESULT_FAILED_PRECONDITION) {
882*635a8641SAndroid Build Coastguard Worker      MojoRemoveTrigger(state->trap, event->trigger_context, NULL);
883*635a8641SAndroid Build Coastguard Worker      return;
884*635a8641SAndroid Build Coastguard Worker    }
885*635a8641SAndroid Build Coastguard Worker  }
886*635a8641SAndroid Build Coastguard Worker}
887*635a8641SAndroid Build Coastguard Worker
888*635a8641SAndroid Build Coastguard WorkerMojoHandle a, b;
889*635a8641SAndroid Build Coastguard WorkerMojoCreateMessagePipe(NULL, &a, &b);
890*635a8641SAndroid Build Coastguard Worker
891*635a8641SAndroid Build Coastguard WorkerMojoHandle a_trap, b_trap;
892*635a8641SAndroid Build Coastguard WorkerMojoCreateTrap(&OnNotification, NULL, &a_trap);
893*635a8641SAndroid Build Coastguard WorkerMojoCreateTrap(&OnNotification, NULL, &b_trap)
894*635a8641SAndroid Build Coastguard Worker
895*635a8641SAndroid Build Coastguard Workerstruct WatchedHandleState* a_state = malloc(sizeof(struct WatchedHandleState));
896*635a8641SAndroid Build Coastguard Workera_state->trap = a_trap;
897*635a8641SAndroid Build Coastguard Workera_state->handle = a;
898*635a8641SAndroid Build Coastguard Workera_state->message_count = 0;
899*635a8641SAndroid Build Coastguard Worker
900*635a8641SAndroid Build Coastguard Workerstruct WatchedHandleState* b_state = malloc(sizeof(struct WatchedHandleState));
901*635a8641SAndroid Build Coastguard Workerb_state->trap = b_trap;
902*635a8641SAndroid Build Coastguard Workerb_state->handle = b;
903*635a8641SAndroid Build Coastguard Workerb_state->message_count = 0;
904*635a8641SAndroid Build Coastguard Worker
905*635a8641SAndroid Build Coastguard WorkerMojoAddTrigger(a_trap, a, MOJO_HANDLE_SIGNAL_READABLE,
906*635a8641SAndroid Build Coastguard Worker               MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, (uintptr_t)a_state,
907*635a8641SAndroid Build Coastguard Worker               NULL);
908*635a8641SAndroid Build Coastguard WorkerMojoAddTrigger(b_trap, b, MOJO_HANDLE_SIGNAL_READABLE,
909*635a8641SAndroid Build Coastguard Worker               MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, (uintptr_t)b_state,
910*635a8641SAndroid Build Coastguard Worker               NULL);
911*635a8641SAndroid Build Coastguard Worker
912*635a8641SAndroid Build Coastguard WorkerMojoArmTrap(a_trap, NULL, NULL, NULL);
913*635a8641SAndroid Build Coastguard WorkerMojoArmTrap(b_trap, NULL, NULL, NULL);
914*635a8641SAndroid Build Coastguard Worker```
915*635a8641SAndroid Build Coastguard Worker
916*635a8641SAndroid Build Coastguard WorkerNow any writes to `a` will increment `message_count` in `b_state`, and any
917*635a8641SAndroid Build Coastguard Workerwrites to `b` will increment `message_count` in `a_state`.
918*635a8641SAndroid Build Coastguard Worker
919*635a8641SAndroid Build Coastguard WorkerIf either `a` or `b` is closed, both watches will be cancelled - one because
920*635a8641SAndroid Build Coastguard Workerwatch cancellation is implicit in handle closure, and the other because its
921*635a8641SAndroid Build Coastguard Workerwatcher will eventually detect that the handle is no longer readable.
922*635a8641SAndroid Build Coastguard Worker
923*635a8641SAndroid Build Coastguard Worker## Invitations
924*635a8641SAndroid Build Coastguard Worker
925*635a8641SAndroid Build Coastguard WorkerTODO.
926*635a8641SAndroid Build Coastguard Worker
927*635a8641SAndroid Build Coastguard WorkerFor now see the
928*635a8641SAndroid Build Coastguard Worker[C header](https://cs.chromium.org/src/mojo/public/c/system/invitation.h) and
929*635a8641SAndroid Build Coastguard Workerthe documentation for the equivalent
930*635a8641SAndroid Build Coastguard Worker[C++ API](/mojo/public/cpp/system/README.md#Invitations).
931