Reference#

C++ API reference#

pw_channel: Async, zero-copy API for sending and receiving bytes or datagrams

template<Property... kProperties>
using ByteChannel = Channel<DataType::kByte, kProperties...>#

A ByteChannel exchanges data as a stream of bytes.

template<Property... kProperties>
using DatagramChannel = Channel<DataType::kDatagram, kProperties...>#

A DatagramChannel exchanges data as a series of datagrams.

using ByteReader = ByteChannel<kReadable>#

Unreliable byte-oriented Channel that supports reading.

using ByteWriter = ByteChannel<kWritable>#

Unreliable byte-oriented Channel that supports writing.

using ByteReaderWriter = ByteChannel<kReadable, kWritable>#

Unreliable byte-oriented Channel that supports reading and writing.

using ReliableByteReader = ByteChannel<kReliable, kReadable>#

Reliable byte-oriented Channel that supports reading.

using ReliableByteWriter = ByteChannel<kReliable, kWritable>#

Reliable byte-oriented Channel that supports writing.

using ReliableByteReaderWriter = ByteChannel<kReliable, kReadable, kWritable>#

Reliable byte-oriented Channel that supports reading and writing.

using DatagramReader = DatagramChannel<kReadable>#

Unreliable datagram-oriented Channel that supports reading.

using DatagramWriter = DatagramChannel<kWritable>#

Unreliable datagram-oriented Channel that supports writing.

using DatagramReaderWriter = DatagramChannel<kReadable, kWritable>#

Unreliable datagram-oriented Channel that supports reading and writing.

using ReliableDatagramReader = DatagramChannel<kReliable, kReadable>#

Reliable datagram-oriented Channel that supports reading.

using ReliableDatagramWriter = DatagramChannel<kReliable, kWritable>#

Reliable datagram-oriented Channel that supports writing.

using ReliableDatagramReaderWriter = DatagramChannel<kReliable, kReadable, kWritable>#

Reliable datagram-oriented Channel that supports reading and writing.

template<Property... kProperties>
using ByteChannelImpl = ChannelImpl<DataType::kByte, kProperties...>#

Implement a byte-oriented Channel with the specified properties.

template<Property... kProperties>
using DatagramChannelImpl = ChannelImpl<DataType::kDatagram, kProperties...>#

Implement a datagram-oriented Channel with the specified properties.

template<DataType kDataType, Property... kProperties>
class Channel#

The basic Channel type. Unlike AnyChannel, the Channel’s properties are expressed in template parameters and thus reflected in the type.

Properties must be specified in order (kDatagram, kReliable, kReadable, kWritable, kSeekable) and without duplicates.

To implement a Channel, inherit from ChannelImpl with the specified properties.

Subclassed by pw::bluetooth::low_energy::Channel

Public Functions

constexpr bool is_read_open() const#

True if the channel type supports and is open for reading. Always false for write-only channels.

constexpr bool is_write_open() const#

True if the channel type supports and is open for writing. Always false for read-only channels.

inline constexpr bool is_read_or_write_open() const#

True if the channel is open for reading or writing.

async2::Poll<Result<multibuf::MultiBuf>> PendRead(async2::Context &cx)#

Returns a pw::multibuf::MultiBuf with read data, if available. If data is not available, invokes cx.waker() when it becomes available.

For datagram channels, each successful read yields one complete datagram, which may contain zero or more bytes. For byte stream channels, each successful read yields one or more bytes.

Channels only support one read operation / waker at a time.

Returns:

Code

Description

OK

Data was read into a MultiBuf.

UNIMPLEMENTED

The channel does not support reading.

FAILED_PRECONDITION

The channel is closed.

OUT_OF_RANGE

The end of the stream was reached. This may be though of as reaching the end of a file. Future reads may succeed after Seek ing backwards, but no more new data will be produced. The channel is still open; writes and seeks may succeed.

async2::Poll<Status> PendReadyToWrite(pw::async2::Context &cx)#

Checks whether a writeable channel is currently writeable.

This should be called before attempting to Write, and may be called before allocating a write buffer if trying to reduce memory pressure.

This method will return:

  • Ready(OK) - The channel is currently writeable, and a single caller may proceed to Write.

  • Ready(UNIMPLEMENTED) - The channel does not support writing.

  • Ready(FAILED_PRECONDITION) - The channel is closed for writing.

  • Pending - cx will be awoken when the channel becomes writeable again.

Note: this method will always return Ready for non-writeable channels.

Status StageWrite(multibuf::MultiBuf &&data)#

Writes using a previously allocated MultiBuf. Returns a token that refers to this write. These tokens are monotonically increasing, and PendWrite() returns the value of the latest token it has flushed.

The MultiBuf argument to Write may consist of either: (1) A single MultiBuf allocated by PendAllocateWriteBuffer that has not been combined with any other MultiBuf s or Chunks OR (2) A MultiBuf containing any combination of buffers from sources other than PendAllocateWriteBuffer.

This requirement allows for more efficient use of memory in case (1). For example, a ring-buffer implementation of a Channel may specialize PendAllocateWriteBuffer to return the next section of the buffer available for writing.

Returns:

May fail with the following error codes:

Code

Description

OK

Data was accepted by the channel.

UNIMPLEMENTED

The channel does not support writing.

UNAVAILABLE

The write failed due to a transient error (only applies to unreliable channels).

FAILED_PRECONDITION

The channel is closed.

async2::Poll<Status> PendWrite(async2::Context &cx)#

Completes pending writes.

Returns a async2::Poll indicating whether or the write has completed.

  • Ready(OK) - All data has been successfully written.

  • Ready(UNIMPLEMENTED) - The channel does not support writing.

  • Ready(FAILED_PRECONDITION) - The channel is closed.

  • Pending - Writing is not complete.

async2::Poll<pw::Status> PendClose(async2::Context &cx)#

Closes the channel, flushing any data.

Returns:

Code

Description

OK

The channel was closed and all data was sent successfully.

DATA_LOSS

The channel was closed, but not all previously written data was delivered.

FAILED_PRECONDITION

Channel was already closed, which can happen out-of-band due to errors.

template<typename Sibling, typename = internal::EnableIfConversionIsValid<Channel, Sibling>>
inline constexpr operator Sibling&(
)#

Channels may be implicitly converted to other compatible channel types.

template<typename Sibling>
inline Sibling &as()#

Returns a reference to this channel as another compatible channel type.

template<Property... kOtherChannelProperties>
inline auto &as()#

Returns a reference to this channel as another channel with the specified properties, which must be compatible.

Public Static Functions

static inline constexpr DataType data_type()#

Returns the data type of this channel.

static inline constexpr bool reliable()#

Returns whether the channel type is reliable.

static inline constexpr bool seekable()#

Returns whether the channel type is seekable.

static inline constexpr bool readable()#

Returns whether the channel type is readable.

static inline constexpr bool writable()#

Returns whether the channel type is writable.

class AnyChannel : private pw::channel::Channel<DataType::kByte, kReadable>, private pw::channel::Channel<DataType::kByte, kWritable>, private pw::channel::Channel<DataType::kByte, kReadable, kWritable>, private pw::channel::Channel<DataType::kByte, kReliable, kReadable>, private pw::channel::Channel<DataType::kByte, kReliable, kWritable>, private pw::channel::Channel<DataType::kByte, kReliable, kReadable, kWritable>, private pw::channel::Channel<DataType::kDatagram, kReadable>, private pw::channel::Channel<DataType::kDatagram, kWritable>, private pw::channel::Channel<DataType::kDatagram, kReadable, kWritable>, private pw::channel::Channel<DataType::kDatagram, kReliable, kReadable>, private pw::channel::Channel<DataType::kDatagram, kReliable, kWritable>, private pw::channel::Channel<DataType::kDatagram, kReliable, kReadable, kWritable>#

A generic data channel that may support reading or writing bytes or datagrams.

Note that this channel should be used from only one pw::async::Task at a time, as the Pend methods are only required to remember the latest pw::async2::Context that was provided. Notably, this means that it is not possible to read from the channel in one task while writing to it from another task: a single task must own and operate the channel. In the future, a wrapper will be offered which will allow the channel to be split into a read half and a write half which can be used from independent tasks.

To implement a Channel, inherit from ChannelImpl with the specified properties.

Public Functions

inline constexpr DataType data_type() const#

Returns the data type of the channel implementation.

inline constexpr bool reliable() const#

Returns whether the channel implementation is reliable.

inline constexpr bool seekable() const#

Returns whether the channel implementation is seekable.

inline constexpr bool readable() const#

Returns whether the channel implementation is readable.

inline constexpr bool writable() const#

Returns whether the channel implementation is writable.

inline constexpr bool is_read_open() const#

True if the channel is open for reading. Always false for write-only channels.

inline constexpr bool is_write_open() const#

True if the channel is open for writing. Always false for read-only channels.

inline constexpr bool is_read_or_write_open() const#

True if the channel is open for either reading or writing.

inline async2::Poll<Result<multibuf::MultiBuf>> PendRead(async2::Context &cx)#

Returns a pw::multibuf::MultiBuf with read data, if available. If data is not available, invokes cx.waker() when it becomes available.

For datagram channels, each successful read yields one complete datagram, which may contain zero or more bytes. For byte stream channels, each successful read yields one or more bytes.

Channels only support one read operation / waker at a time.

Returns:

Code

Description

OK

Data was read into a MultiBuf.

UNIMPLEMENTED

The channel does not support reading.

FAILED_PRECONDITION

The channel is closed.

OUT_OF_RANGE

The end of the stream was reached. This may be though of as reaching the end of a file. Future reads may succeed after Seek ing backwards, but no more new data will be produced. The channel is still open; writes and seeks may succeed.

inline async2::Poll<Status> PendReadyToWrite(pw::async2::Context &cx)#

Checks whether a writeable channel is currently writeable.

This should be called before attempting to Write, and may be called before allocating a write buffer if trying to reduce memory pressure.

This method will return:

  • Ready(OK) - The channel is currently writeable, and a single caller may proceed to Write.

  • Ready(UNIMPLEMENTED) - The channel does not support writing.

  • Ready(FAILED_PRECONDITION) - The channel is closed for writing.

  • Pending - cx will be awoken when the channel becomes writeable again.

Note: this method will always return Ready for non-writeable channels.

inline async2::Poll<std::optional<multibuf::MultiBuf>> PendAllocateWriteBuffer(async2::Context &cx, size_t min_bytes)#

Attempts to allocate a write buffer of at least min_bytes bytes.

On success, returns a MultiBuf of at least min_bytes. This buffer should be filled with data and then passed back into StageWrite. The user may shrink or fragment the MultiBuf during its own usage of the buffer, but the MultiBuf should be restored to its original shape before it is passed to StageWrite.

Users should not wait on the result of PendAllocateWriteBuffer while holding an existing MultiBuf from PendAllocateWriteBuffer, as this can result in deadlocks.

This method will return:

  • Ready(buffer) - A buffer of the requested size is provided.

  • Ready(std::nullopt) - min_bytes is larger than the maximum buffer size this channel can allocate.

  • Pending - No buffer of at least min_bytes is available. The task associated with the provided pw::async2::Context will be awoken when a sufficiently-sized buffer becomes available.

inline Status StageWrite(multibuf::MultiBuf &&data)#

Writes using a previously allocated MultiBuf. Returns a token that refers to this write. These tokens are monotonically increasing, and PendWrite() returns the value of the latest token it has flushed.

The MultiBuf argument to Write may consist of either: (1) A single MultiBuf allocated by PendAllocateWriteBuffer that has not been combined with any other MultiBuf s or Chunks OR (2) A MultiBuf containing any combination of buffers from sources other than PendAllocateWriteBuffer.

This requirement allows for more efficient use of memory in case (1). For example, a ring-buffer implementation of a Channel may specialize PendAllocateWriteBuffer to return the next section of the buffer available for writing.

Returns:

May fail with the following error codes:

Code

Description

OK

Data was accepted by the channel.

UNIMPLEMENTED

The channel does not support writing.

UNAVAILABLE

The write failed due to a transient error (only applies to unreliable channels).

FAILED_PRECONDITION

The channel is closed.

inline async2::Poll<Status> PendWrite(async2::Context &cx)#

Completes pending writes.

Returns a async2::Poll indicating whether or the write has completed.

  • Ready(OK) - All data has been successfully written.

  • Ready(UNIMPLEMENTED) - The channel does not support writing.

  • Ready(FAILED_PRECONDITION) - The channel is closed.

  • Pending - Writing is not complete.

Status Seek(async2::Context &cx, ptrdiff_t position, Whence whence)#

Seek changes the position in the stream.

TODO: b/323622630 - Seek and Position are not yet implemented.

Any PendRead or Write calls following a call to Seek will be relative to the new position. Already-written data still being flushed will be output relative to the old position.

Returns:

Code

Description

OK

The current position was successfully changed.

UNIMPLEMENTED

The channel does not support seeking.

FAILED_PRECONDITION

The channel is closed.

NOT_FOUND

The seek was to a valid position, but the channel is no longer capable of seeking to this position (partially seekable channels only).

OUT_OF_RANGE

The seek went beyond the end of the stream.

size_t Position() const#

Returns the current position in the stream, or kUnknownPosition if unsupported.

TODO: b/323622630 - Seek and Position are not yet implemented.

inline async2::Poll<pw::Status> PendClose(async2::Context &cx)#

Closes the channel, flushing any data.

Returns:

Code

Description

OK

The channel was closed and all data was sent successfully.

DATA_LOSS

The channel was closed, but not all previously written data was delivered.

FAILED_PRECONDITION

Channel was already closed, which can happen out-of-band due to errors.

template<DataType kDataType, Property... kProperties>
class ChannelImpl#

Extend ChannelImpl to implement a channel with the specified properties. Unavailable methods on the channel will be stubbed out.

Alternately, inherit from pw::channel::Implement with a channel reader/writer alias as the template parameter.

A ChannelImpl has a corresponding Channel type (ChannelImpl<>::Channel). Call the channel() method to convert the ChannelImpl to its corresponding Channel.

template<typename ChannelType>
class Implement#

Implement the specified Channel type. This is intended for use with the reader/writer aliases:

class MyChannel : public pw::channel::Implement<pw::channel::ByteReader> {};

Channel implementations#

using ForwardingDatagramChannelPair = ForwardingChannelPair<DataType::kDatagram>#

Alias for a pair of forwarding datagram channels.

using ForwardingByteChannelPair = ForwardingChannelPair<DataType::kByte>#

Alias for a pair of forwarding byte channels.

template<DataType kType>
class ForwardingChannelPair#

Forwards either datagrams or bytes between two channels. Writes to the first channel appear as reads on the second, and vice versa.

ForwardingChannelPair enables connecting two subsystems that communicate with channels without implementing a custom channel.

Public Functions

inline Channel<kType, kReliable, kReadable, kWritable> &first()#

Returns the first channel in the pair.

inline const Channel<kType, kReliable, kReadable, kWritable> &first() const#

Returns a const reference to the first channel in the pair.

inline Channel<kType, kReliable, kReadable, kWritable> &second()#

Returns the second channel in the pair.

inline const Channel<kType, kReliable, kReadable, kWritable> &second() const#

Returns a const reference to the second channel in the pair.

using LoopbackDatagramChannel = LoopbackChannel<DataType::kDatagram>#

Alias for a loopback channel that sends and receives datagrams.

using LoopbackByteChannel = LoopbackChannel<DataType::kByte>#

Alias for a loopback channel that sends and receives bytes.

template<DataType kType>
class LoopbackChannel#
class EpollChannel : public pw::channel::Implement<ByteReaderWriter>#

Channel implementation which writes to and reads from a file descriptor, backed by Linux’s epoll notification system.

This channel depends on APIs provided by the EpollDispatcher and cannot be used with any other dispatcher backend.

An instantiated EpollChannel takes ownership of the file descriptor it is given, and will close it if the channel is closed or destroyed. Users should not close a channel’s file descriptor from outside.

ByteReaderWriter &Rp2StdioChannelInit(
pw::multibuf::MultiBufAllocator &read_allocator,
pw::multibuf::MultiBufAllocator &write_allocator,
)#

Initializes and returns a reference to a channel that speaks over rp2’s stdio.

ByteReaderWriter &Rp2StdioChannelInit(pw::multibuf::MultiBufAllocator &allocator)#

DEPRECATED: prefer the two-allocator version of this API to avoid deadlocks due to the read or write side of the API attempting to acquire more memory while the other holds it.

Initializes and returns a reference to a channel that speaks over rp2’s stdio.

class StreamChannel : public pw::channel::Implement<channel::ByteReaderWriter>#

A channel which delegates to an underlying reader and writer stream.

NOTE: this channel as well as its reader and writer must all continue to exist for the duration of the program, as they are referenced by other threads.

This unfortunate requirement is due to the fact that Stream::Read and Stream::Write are blocking. The stream reading and writing threaads may be blocked on Read or Write calls, and therefore cannot cleanly be shutdown.