summaryrefslogtreecommitdiff
path: root/mojo/public/c/system/data_pipe.h
blob: 3702cdb62493a29614d9b2c0644f9d31d8ab621c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file contains types/constants and functions specific to data pipes.
//
// Note: This header should be compilable as C.

#ifndef MOJO_PUBLIC_C_SYSTEM_DATA_PIPE_H_
#define MOJO_PUBLIC_C_SYSTEM_DATA_PIPE_H_

#include <stdint.h>

#include "mojo/public/c/system/macros.h"
#include "mojo/public/c/system/system_export.h"
#include "mojo/public/c/system/types.h"

// Flags passed to |MojoCreateDataPipe()| via |MojoCreateDataPipeOptions|. See
// values defined below.
typedef uint32_t MojoCreateDataPipeFlags;

// No flags. Default behavior.
#define MOJO_CREATE_DATA_PIPE_FLAG_NONE ((uint32_t)0)

// Options passed to |MojoCreateDataPipe()|.
struct MOJO_ALIGNAS(8) MojoCreateDataPipeOptions {
  // The size of this structure, used for versioning.
  uint32_t struct_size;

  // See |MojoCreateDataPipeFlags|.
  MojoCreateDataPipeFlags flags;

  // The size of an element in bytes. All transactions and buffer sizes must
  // consist of an integral number of elements. Must be non-zero.
  uint32_t element_num_bytes;

  // The capacity of the data pipe in bytes. Must be a multiple of
  // |element_num_bytes|. If successfully created, the pipe will always be able
  // to queue at least this much data. If zero, the pipe buffer will be of a
  // system-dependent capacity of at least one element in size.
  uint32_t capacity_num_bytes;
};
MOJO_STATIC_ASSERT(MOJO_ALIGNOF(int64_t) == 8, "int64_t has weird alignment");
MOJO_STATIC_ASSERT(sizeof(MojoCreateDataPipeOptions) == 16,
                   "MojoCreateDataPipeOptions has wrong size");

// Flags passed to |MojoWriteData()| via |MojoWriteDataOptions|. See values
// defined below.
typedef uint32_t MojoWriteDataFlags;

// No flags. Default behavior.
#define MOJO_WRITE_DATA_FLAG_NONE ((uint32_t)0)

// Requires that all provided data must fit into the pipe's available capacity
// in order for the write to succeed. Otherwise the write fails and no data is
// written into the pipe.
#define MOJO_WRITE_DATA_FLAG_ALL_OR_NONE ((uint32_t)1 << 0)

// Options passed to |MojoWriteData()|.
struct MOJO_ALIGNAS(8) MojoWriteDataOptions {
  // The size of this structure, used for versioning.
  uint32_t struct_size;

  // See |MojoWriteDataFlags|.
  MojoWriteDataFlags flags;
};
MOJO_STATIC_ASSERT(sizeof(MojoWriteDataOptions) == 8,
                   "MojoWriteDataOptions has wrong size");

// Flags passed to |MojoBeginWriteData()| via |MojoBeginWriteDataOptions|. See
// values defined below.
typedef uint32_t MojoBeginWriteDataFlags;

// No flags. Default behavior.
#define MOJO_BEGIN_WRITE_DATA_FLAG_NONE ((uint32_t)0)

// Options passed to |MojoBeginWriteData()|.
struct MOJO_ALIGNAS(8) MojoBeginWriteDataOptions {
  // The size of this structure, used for versioning.
  uint32_t struct_size;

  // See |MojoBeginWriteDataFlags|.
  MojoBeginWriteDataFlags flags;
};
MOJO_STATIC_ASSERT(sizeof(MojoBeginWriteDataOptions) == 8,
                   "MojoBeginWriteDataOptions has wrong size");

// Flags passed to |MojoEndWriteData()| via |MojoEndWriteDataOptions|. See
// values defined below.
typedef uint32_t MojoEndWriteDataFlags;

// No flags. Default behavior.
#define MOJO_END_WRITE_DATA_FLAG_NONE ((uint32_t)0)

// Options passed to |MojoEndWriteData()|.
struct MOJO_ALIGNAS(8) MojoEndWriteDataOptions {
  // The size of this structure, used for versioning.
  uint32_t struct_size;

  // See |MojoEndWriteDataFlags|.
  MojoEndWriteDataFlags flags;
};
MOJO_STATIC_ASSERT(sizeof(MojoEndWriteDataOptions) == 8,
                   "MojoEndWriteDataOptions has wrong size");

// Flags passed to |MojoReadData()| via |MojoReadDataOptions|.
typedef uint32_t MojoReadDataFlags;

// No flags. Default behavior.
#define MOJO_READ_DATA_FLAG_NONE ((uint32_t)0)

// Requires that all request bytes can be read from the data pipe in order for
// the read to succeed. If that many bytes are not available for reading, the
// read will fail and no bytes will be read. Ignored of
// |MOJO_READ_DATA_FLAG_QUERY| is also set.
#define MOJO_READ_DATA_FLAG_ALL_OR_NONE ((uint32_t)1 << 0)

// Discards the data read rather than copying it into the caller's provided
// buffer. May not be combined with |MOJO_READ_DATA_FLAG_PEEK| or
// |MOJO_READ_DATA_FLAG_QUERY|.
#define MOJO_READ_DATA_FLAG_DISCARD ((uint32_t)1 << 1)

// Queries the number of bytes available for reading without actually reading
// the data. May not be combined with |MOJO_READ_DATA_FLAG_DISCARD| or
// |MOJO_READ_DATA_FLAG_PEEK|. |MOJO_READ_DATA_FLAG_ALL_OR_NONE| is ignored if
// this is set.
#define MOJO_READ_DATA_FLAG_QUERY ((uint32_t)1 << 2)

// Reads data from the pipe and copies it to the caller's provided buffer
// without actually removing the data from the pipe. May not be combined with
// |MOJO_READ_DATA_FLAG_DISCARD| or |MOJO_READ_DATA_FLAG_QUERY|.
#define MOJO_READ_DATA_FLAG_PEEK ((uint32_t)1 << 3)

// Options passed to |MojoReadData()|.
struct MOJO_ALIGNAS(8) MojoReadDataOptions {
  // The size of this structure, used for versioning.
  uint32_t struct_size;

  // See |MojoReadDataFlags|.
  MojoReadDataFlags flags;
};
MOJO_STATIC_ASSERT(sizeof(MojoReadDataOptions) == 8,
                   "MojoReadDataOptions has wrong size");

// Flags passed to |MojoBeginReadData()| via |MojoBeginReadDataOptions|. See
// values defined below.
typedef uint32_t MojoBeginReadDataFlags;

// No flags. Default behavior.
#define MOJO_BEGIN_READ_DATA_FLAG_NONE ((uint32_t)0)

// Options passed to |MojoBeginReadData()|.
struct MOJO_ALIGNAS(8) MojoBeginReadDataOptions {
  // The size of this structure, used for versioning.
  uint32_t struct_size;

  // See |MojoBeginReadDataFlags|.
  MojoBeginReadDataFlags flags;
};
MOJO_STATIC_ASSERT(sizeof(MojoBeginReadDataOptions) == 8,
                   "MojoBeginReadDataOptions has wrong size");

// Flags passed to |MojoEndReadData()| via |MojoEndReadDataOptions|. See
// values defined below.
typedef uint32_t MojoEndReadDataFlags;

// No flags. Default behavior.
#define MOJO_END_READ_DATA_FLAG_NONE ((uint32_t)0)

// Options passed to |MojoEndReadData()|.
struct MOJO_ALIGNAS(8) MojoEndReadDataOptions {
  // The size of this structure, used for versioning.
  uint32_t struct_size;

  // See |MojoEndReadDataFlags|.
  MojoEndReadDataFlags flags;
};
MOJO_STATIC_ASSERT(sizeof(MojoEndReadDataOptions) == 8,
                   "MojoEndReadDataOptions has wrong size");

#ifdef __cplusplus
extern "C" {
#endif

// Creates a data pipe, which is a unidirectional communication channel for
// unframed data. Data must be read and written in multiples of discrete
// discrete elements of size given in |options|.
//
// See |MojoCreateDataPipeOptions| for a description of the different options
// available for data pipes.
//
// |options| may be set to null for a data pipe with the default options (which
// will have an element size of one byte and have some system-dependent
// capacity).
//
// On success, |*data_pipe_producer_handle| will be set to the handle for the
// producer and |*data_pipe_consumer_handle| will be set to the handle for the
// consumer. On failure they are not modified.
//
// Returns:
//   |MOJO_RESULT_OK| on success.
//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid, e.g.,
//       |*options| is invalid, specified capacity or element size is zero, or
//       the specified element size exceeds the specified capacity.
//   |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has
//       been reached (e.g., if the requested capacity was too large, or if the
//       maximum number of handles was exceeded).
//   |MOJO_RESULT_UNIMPLEMENTED| if an unsupported flag was set in |*options|.
MOJO_SYSTEM_EXPORT MojoResult
MojoCreateDataPipe(const struct MojoCreateDataPipeOptions* options,
                   MojoHandle* data_pipe_producer_handle,
                   MojoHandle* data_pipe_consumer_handle);

// Writes the data pipe producer given by |data_pipe_producer_handle|.
//
// |elements| points to data of size |*num_bytes|; |*num_bytes| must be a
// multiple of the data pipe's element size.
//
// On success |*num_bytes| is set to the amount of data that was actually
// written. On failure it is unmodified.
//
// |options| may be null for default options. See |MojoWriteDataOptions| for
// the effect of various options on the behavior of this function.
//
// Returns:
//   |MOJO_RESULT_OK| on success.
//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g.,
//       |data_pipe_producer_dispatcher| is not a handle to a data pipe
//       producer or |*num_bytes| is not a multiple of the data pipe's element
//       size.)
//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer handle has been
//       closed.
//   |MOJO_RESULT_OUT_OF_RANGE| if |options->flags| has
//       |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set and the required amount of data
//       (specified by |*num_bytes|) could not be written.
//   |MOJO_RESULT_BUSY| if there is a two-phase write ongoing with
//       |data_pipe_producer_handle| (i.e., |MojoBeginWriteData()| has been
//       called, but not yet the matching |MojoEndWriteData()|).
//   |MOJO_RESULT_SHOULD_WAIT| if no data can currently be written (and the
//       consumer is still open) and |options->flags| does *not* have
//       |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set.
MOJO_SYSTEM_EXPORT MojoResult
MojoWriteData(MojoHandle data_pipe_producer_handle,
              const void* elements,
              uint32_t* num_bytes,
              const struct MojoWriteDataOptions* options);

// Begins a two-phase write to the data pipe producer given by
// |data_pipe_producer_handle|. On success |*buffer| will be a pointer to which
// the caller can write up to |*buffer_num_bytes| bytes of data.
//
// During a two-phase write, |data_pipe_producer_handle| is *not* writable.
// If another caller tries to write to it by calling |MojoWriteData()| or
// |MojoBeginWriteData()|, their request will fail with |MOJO_RESULT_BUSY|.
//
// If |MojoBeginWriteData()| returns MOJO_RESULT_OK and once the caller has
// finished writing data to |*buffer|, |MojoEndWriteData()| must be called to
// indicate the amount of data actually written and to complete the two-phase
// write operation. |MojoEndWriteData()| need not be called when
// |MojoBeginWriteData()| fails.
//
// |options| may be null for default options.
//
// Returns:
//   |MOJO_RESULT_OK| on success.
//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g.,
//       |data_pipe_producer_handle| is not a handle to a data pipe producer or
//       |*options| is invalid.
//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer handle has been
//       closed.
//   |MOJO_RESULT_BUSY| if there is already a two-phase write ongoing with
//       |data_pipe_producer_handle| (i.e., |MojoBeginWriteData()| has been
//       called, but not yet the matching |MojoEndWriteData()|).
//   |MOJO_RESULT_SHOULD_WAIT| if no data can currently be written (and the
//       consumer is still open).
MOJO_SYSTEM_EXPORT MojoResult
MojoBeginWriteData(MojoHandle data_pipe_producer_handle,
                   const struct MojoBeginWriteDataOptions* options,
                   void** buffer,
                   uint32_t* buffer_num_bytes);

// Ends a two-phase write that was previously initiated by
// |MojoBeginWriteData()| for the same |data_pipe_producer_handle|.
//
// |num_bytes_written| must indicate the number of bytes actually written into
// the two-phase write buffer. It must be less than or equal to the value of
// |*buffer_num_bytes| output by |MojoBeginWriteData()|, and it must be a
// multiple of the data pipe's element size.
//
// On failure, the two-phase write (if any) is ended (so the handle may become
// writable again if there's space available) but no data written to |*buffer|
// is "put into" the data pipe.
//
// |options| may be null for default options.
//
// Returns:
//   |MOJO_RESULT_OK| on success.
//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g.,
//       |data_pipe_producer_handle| is not a handle to a data pipe producer or
//       |num_bytes_written| is invalid (greater than the maximum value provided
//       by |MojoBeginWriteData()| or not a multiple of the element size).
//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer is not in a
//       two-phase write (e.g., |MojoBeginWriteData()| was not called or
//       |MojoEndWriteData()| has already been called).
MOJO_SYSTEM_EXPORT MojoResult
MojoEndWriteData(MojoHandle data_pipe_producer_handle,
                 uint32_t num_bytes_written,
                 const struct MojoEndWriteDataOptions* options);

// Reads data from the data pipe consumer given by |data_pipe_consumer_handle|.
// May also be used to discard data or query the amount of data available.
//
// If |options->flags| has neither |MOJO_READ_DATA_FLAG_DISCARD| nor
// |MOJO_READ_DATA_FLAG_QUERY| set, this tries to read up to |*num_bytes| (which
// must be a multiple of the data pipe's element size) bytes of data to
// |elements| and set |*num_bytes| to the amount actually read. If flags has
// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set, it will either read exactly
// |*num_bytes| bytes of data or none. Additionally, if flags has
// |MOJO_READ_DATA_FLAG_PEEK| set, the data read will remain in the pipe and be
// available to future reads.
//
// If flags has |MOJO_READ_DATA_FLAG_DISCARD| set, it discards up to
// |*num_bytes| (which again must be a multiple of the element size) bytes of
// data, setting |*num_bytes| to the amount actually discarded. If flags has
// |MOJO_READ_DATA_FLAG_ALL_OR_NONE|, it will either discard exactly
// |*num_bytes| bytes of data or none. In this case, |MOJO_READ_DATA_FLAG_QUERY|
// must not be set, and |elements| is ignored (and should typically be set to
// null).
//
// If flags has |MOJO_READ_DATA_FLAG_QUERY| set, it queries the amount of data
// available, setting |*num_bytes| to the number of bytes available. In this
// case, |MOJO_READ_DATA_FLAG_DISCARD| must not be set, and
// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| is ignored, as are |elements| and the input
// value of |*num_bytes|.
//
// |options| may be null for default options.
//
// Returns:
//   |MOJO_RESULT_OK| on success (see above for a description of the different
//       operations).
//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g.,
//       |data_pipe_consumer_handle| is invalid, the combination of flags in
//       |options->flags| is invalid, or |*options| itself is invalid).
//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer handle has been
//       closed and data (or the required amount of data) was not available to
//       be read or discarded.
//   |MOJO_RESULT_OUT_OF_RANGE| if |options->flags| has
//       |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set and the required amount of data
//       is not available to be read or discarded and the producer is still
//       open.
//   |MOJO_RESULT_BUSY| if there is a two-phase read ongoing with
//       |data_pipe_consumer_handle| (i.e., |MojoBeginReadData()| has been
//       called, but not yet the matching |MojoEndReadData()|).
//   |MOJO_RESULT_SHOULD_WAIT| if there is no data to be read or discarded (and
//       the producer is still open) and |options->flags| does *not* have
//       |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set.
MOJO_SYSTEM_EXPORT MojoResult
MojoReadData(MojoHandle data_pipe_consumer_handle,
             const struct MojoReadDataOptions* options,
             void* elements,
             uint32_t* num_bytes);

// Begins a two-phase read from the data pipe consumer given by
// |data_pipe_consumer_handle|. On success, |*buffer| will be a pointer from
// which the caller can read up to |*buffer_num_bytes| bytes of data.
//
// During a two-phase read, |data_pipe_consumer_handle| is *not* readable.
// If another caller tries to read from it by calling |MojoReadData()| or
// |MojoBeginReadData()|, their request will fail with |MOJO_RESULT_BUSY|.
//
// Once the caller has finished reading data from |*buffer|, |MojoEndReadData()|
// must be called to indicate the number of bytes read and to complete the
// two-phase read operation.
//
// |options| may be null for default options.
//
// Returns:
//   |MOJO_RESULT_OK| on success.
//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g.,
//       |data_pipe_consumer_handle| is not a handle to a data pipe consumer,
//       or |*options| is invalid.)
//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer handle has been
//       closed.
//   |MOJO_RESULT_BUSY| if there is already a two-phase read ongoing with
//       |data_pipe_consumer_handle| (i.e., |MojoBeginReadData()| has been
//       called, but not yet the matching |MojoEndReadData()|).
//   |MOJO_RESULT_SHOULD_WAIT| if no data can currently be read (and the
//       producer is still open).
MOJO_SYSTEM_EXPORT MojoResult
MojoBeginReadData(MojoHandle data_pipe_consumer_handle,
                  const struct MojoBeginReadDataOptions* options,
                  const void** buffer,
                  uint32_t* buffer_num_bytes);

// Ends a two-phase read from the data pipe consumer given by
// |data_pipe_consumer_handle| that was begun by a call to |MojoBeginReadData()|
// on the same handle. |num_bytes_read| should indicate the amount of data
// actually read; it must be less than or equal to the value of
// |*buffer_num_bytes| output by |MojoBeginReadData()| and must be a multiple of
// the element size.
//
// On failure, the two-phase read (if any) is ended (so the handle may become
// readable again) but no data is "removed" from the data pipe.
//
// |options| may be null for default options.
//
// Returns:
//   |MOJO_RESULT_OK| on success.
//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g.,
//       |data_pipe_consumer_handle| is not a handle to a data pipe consumer or
//       |num_bytes_written| is greater than the maximum value provided by
//       |MojoBeginReadData()| or not a multiple of the element size).
//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer is not in a
//       two-phase read (e.g., |MojoBeginReadData()| was not called or
//       |MojoEndReadData()| has already been called).
MOJO_SYSTEM_EXPORT MojoResult
MojoEndReadData(MojoHandle data_pipe_consumer_handle,
                uint32_t num_bytes_read,
                const struct MojoEndReadDataOptions* options);

#ifdef __cplusplus
}  // extern "C"
#endif

#endif  // MOJO_PUBLIC_C_SYSTEM_DATA_PIPE_H_