// 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_