pw_channel#

Warning

This module is in an early, experimental state. Do not rely on its APIs.

Channel attributes#

Channels may be reliable, readable, writable, or seekable. A channel may be substituted for another as long as it provides at least the same set of capabilities; additional capabilities are okay. The channel’s data type (datagram or byte) implies different read/write semantics, so datagram/byte channels cannot be used interchangeably in general.

Using datagram channels as byte channels#

For datagram channels, the exact bytes provided to a write call will appear in a read call on the other end. A zero-byte datagram write results in a zero-byte datagram read, so empty datagrams may convey information.

For byte channels, bytes written may be grouped differently when read. A zero-length byte write is meaningless and will not result in a zero-length byte read. If a zero-length byte read occurs, it is ignored.

To facilitate simple code reuse, datagram-oriented channels may used as byte-oriented channels when appropriate. Calling Channel::IgnoreDatagramBoundaries() on a datagram channel returns a byte channel reference to it. The byte view of the channel is simply the concatenation of the contents of the datagrams.

This is only valid if, for the datagram channel:

  • datagram boundaries have no significance or meaning,

  • zero-length datagrams are not used to convey information, since they are meaningless for byte channels,

  • short or zero-length writes through the byte API will not result in unacceptable overhead.

API reference#

enum Property#

Basic properties of a Channel. A Channel type can convert to any other Channel for which it supports the required properties. For example, a kReadable and kWritable channel may be passed to an API that only requires kReadable.

Values:

enumerator kReliable#

All data is guaranteed to be delivered in order. The channel is closed if data is lost.

enumerator kReadable#

The channel supports reading.

enumerator kWritable#

The channel supports writing.

enumerator kSeekable#

The channel supports seeking (changing the read/write position).

enum class DataType : uint8_t#

The type of data exchanged in Channel read and write calls. Unlike Property, Channels with different DataTypes cannot be used interchangeably.

Values:

enumerator kByte#
enumerator kDatagram#
enum Whence#

Positions from which to seek.

Values:

enumerator kBeginning#

Seek from the beginning of the channel. The offset is a direct offset into the data.

enumerator kCurrent#

Seek from the current position in the channel. The offset is added to the current position. Use a negative offset to seek backwards.

Implementations may only support seeking within a limited range from the current position.

enumerator kEnd#

Seek from the end of the channel. The offset is added to the end position. Use a negative offset to seek backwards from the end.

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<kReliable, kReadable>#

Reliable byte-oriented Channel that supports reading.

using ByteWriter = ByteChannel<kReliable, kWritable>#

Reliable byte-oriented Channel that supports writing.

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

Reliable byte-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.

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.

class WriteToken#

Represents a write operation. WriteToken can be used to track whether a particular write has been flushed.

class AnyChannel#

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.

Subclassed by pw::channel::Channel< kDataType, kProperties >

Public Functions

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

Read API.

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)#

Write API.

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 multibuf::MultiBufAllocator &GetWriteAllocator()#

Gives access to an allocator for write buffers. The MultiBufAllocator provides an asynchronous API for obtaining a buffer.

This allocator must only be used to allocate the next argument to Write. The allocator must be used at most once per call to Write, and the returned MultiBuf must not be combined with any other MultiBuf s or Chunk s.

This method must not be called on channels which do not support writing.

inline Result<WriteToken> Write(multibuf::MultiBuf &&data)#

Writes using a previously allocated MultiBuf. Returns a token that refers to this write. These tokens are monotonically increasing, and PendFlush() 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 GetWriteAllocator() 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 GetWriteAllocator.

This requirement allows for more efficient use of memory in case (1). For example, a ring-buffer implementation of a Channel may specialize GetWriteAllocator 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<Result<WriteToken>> PendFlush(async2::Context &cx)#

Flushes pending writes.

Returns a async2::Poll indicating whether or not flushing has completed.

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

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

  • Ready(FAILED_PRECONDITION) - The channel is closed.

  • Pending - Data remains to be flushed.

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 Channel : public pw::channel::AnyChannel#

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.

Subclassed by pw::channel::LoopbackChannel< DataType::kByte >, pw::channel::LoopbackChannel< DataType::kDatagram >, pw::channel::internal::ForwardingChannel< DataType::kByte >, pw::channel::internal::ForwardingChannel< DataType::kDatagram >

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 datagrams 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 datagram 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#