pw_multibuf#

A buffer API optimized for zero-copy messaging

Unstable C++17

Many forms of device I/O, including sending or receiving messages via RPC, transfer, or sockets, need to deal with multiple buffers or a series of intermediate buffers, each requiring their own copy of the data. pw_multibuf allows data to be written once, eliminating the memory, CPU and latency overhead of copying, and aggregates the memory regions in a manner that is:

  • Flexible: Memory regions can be discontiguous and have different ownership semantics. Memory regions can be added and removed with few restrictions.

  • Copy-averse: Users can pass around and mutate MultiBuf instances without copying or moving data in-memory.

  • Compact: The sequence of memory regions and details about them are stored in only a few words of additional metadata.

 1  MultiBuf::Instance mbuf(allocator);
 2  // DOCSTAG: [pw_multibuf-examples-basic-allocator]
 3
 4  // Add some memory regions.
 5  std::array<std::byte, 16> buffer;
 6  mbuf->PushBack(buffer);
 7  mbuf->Insert(mbuf->begin() + 8, allocator.MakeShared<std::byte[]>(16));
 8  mbuf->PushBack(allocator.MakeUnique<std::byte[]>(16));
 9
10  // Iterate and fill with data.
11  std::fill(mbuf->begin(), mbuf->end(), std::byte(0xFF));
12
13  // Access a discontiguous region.
14  std::array<std::byte, 16> tmp;
15  ConstByteSpan bytes = mbuf->Get(tmp, /*offset=*/16);
16  for (const auto b : bytes) {
17    EXPECT_EQ(static_cast<uint8_t>(b), 0xFF);
18  }
19
20  // Free owned memory.
21  mbuf->Clear();

For the complete example, see pw_multibuf/examples/basic.cc.

What kinds of data is this for?#

pw_multibuf is best used in code that wants to read, write, or pass along data which are one or more of the following:

  • Large: The MultiBuf type allows breaking up data into multiple chunks.

  • Heterogeneous: MultiBuf instances allow combining data that is uniquely owned, shared, or externally managed, and encapsulates the details of deallocating the memory it owns.

  • Latency-sensitive: Since they are copy-averse, MultiBuf instances are useful when working in systems that need to pass large amounts of data, or when memory usage is constrained.

  • Discontiguous: MultiBuf instances provide an interface to accessing and modifying memory regions that encapsulates where the memory actually resides.

  • Communications-oriented: Data which is being received or sent across sockets, various packets, or shared-memory protocols can benefit from the fragmentation, multiplexing, and layering features of the MultiBuf type.

Examples

Learn how to use pw_multibuf through a series of examples

Concepts

Explore the ideas behind pw_multibuf

Design

Learn why pw_multibuf is designed the way it is

API reference

Detailed description of pw_multibuf’s current API

Legacy API

Detailed description of pw_multibuf’s legacy API

Code size analysis

Understand pw_multibuf’s code and memory footprint