Simplex

Introduction

xpp::io::simplex(size) creates a unidirectional pipe — a SimplexReader and SimplexWriter sharing a single ring buffer. Simpler than duplex() which provides two buffers for bidirectional communication. Like Go's io.Pipe.

Works with .await(), co_await (C++20 coroutines), or .then() chains (C++11). Single-threaded.

Example — .await()

#include <xpp/io/simplex.h>

xpp::EventLoop loop;
xpp::WaitScope scope(loop);

auto [reader, writer] = xpp::io::simplex(4096);

writer.write("hello", 5).await();
writer.close();

char buf[8];
reader.read(buf, 8).await();   // buf = "hello"
reader.read(buf, 8).await();   // returns 0 (EOF)

Example — co_await (C++20)

auto [reader, writer] = xpp::io::simplex(4096);

co_await writer.write("hello", 5);
writer.close();

char buf[8];
co_await reader.read(buf, 8);   // buf = "hello"
co_await reader.read(buf, 8);   // returns 0 (EOF)

How it works

simplex(4096)
├── ring buffer (4096 bytes)
├── SimplexReader → reads from buffer, returns 0 on EOF
└── SimplexWriter → writes to buffer, close() signals EOF

write(buf, len):
  copy to buffer → wake reader
read(buf, len):
  copy from buffer → wake writer
close():
  set closed flag → wake reader (EOF)

Writing suspends when the buffer is full; reading suspends when the buffer is empty.

API Reference

MethodReturnsDescription
simplex(size)pair<SimplexReader, SimplexWriter>Create unidirectional pipe with size-byte buffer
SimplexReader::read(buf, len)Promise<ssize_t>Read from pipe. Suspends when empty, 0 on EOF
SimplexWriter::write(buf, len)Promise<ssize_t>Write to pipe. Suspends when buffer full
SimplexWriter::flush()Promise<void>No-op
SimplexWriter::close()voidSignal EOF to reader

Usage Examples

Testing read_all — .await()

xpp::EventLoop loop;
xpp::WaitScope scope(loop);

auto [reader, writer] = xpp::io::simplex(256);
writer.write("hello world", 11).await();
writer.close();

auto data = xpp::io::read_all(reader).await();
// data.size() == 11, data == "hello world"

Testing read_all — co_await (C++20)

auto [reader, writer] = xpp::io::simplex(256);
co_await writer.write("hello world", 11);
writer.close();
auto data = co_await xpp::io::read_all(reader);

Testing copy — .await()

auto [reader, writer] = xpp::io::simplex(256);
writer.write("ping", 4).await();
writer.close();

xpp::io::Empty dst;
xpp::io::copy(reader, dst).await();  // reads "ping" and discards

Testing copy — co_await (C++20)

auto [reader, writer] = xpp::io::simplex(256);
co_await writer.write("ping", 4);
writer.close();
xpp::io::Empty dst;
co_await xpp::io::copy(reader, dst);