xref: /aosp_15_r20/external/pigweed/pw_ring_buffer/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_ring_buffer:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker==============
4*61c4878aSAndroid Build Coastguard Workerpw_ring_buffer
5*61c4878aSAndroid Build Coastguard Worker==============
6*61c4878aSAndroid Build Coastguard WorkerThe ``pw_ring_buffer`` module will eventually provide several ring buffer
7*61c4878aSAndroid Build Coastguard Workerimplementations, each with different tradeoffs.
8*61c4878aSAndroid Build Coastguard Worker
9*61c4878aSAndroid Build Coastguard WorkerThis documentation is incomplete :)
10*61c4878aSAndroid Build Coastguard Worker
11*61c4878aSAndroid Build Coastguard Worker-----------------------
12*61c4878aSAndroid Build Coastguard WorkerPrefixedEntryRingBuffer
13*61c4878aSAndroid Build Coastguard Worker-----------------------
14*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::ring_buffer::PrefixedEntryRingBuffer` is a circular buffer for
15*61c4878aSAndroid Build Coastguard Workerarbitrary length data entries with an optional user-defined preamble byte. It
16*61c4878aSAndroid Build Coastguard Workersupports multiple independent readers.
17*61c4878aSAndroid Build Coastguard Worker
18*61c4878aSAndroid Build Coastguard WorkerIterator
19*61c4878aSAndroid Build Coastguard Worker========
20*61c4878aSAndroid Build Coastguard WorkerIn crash contexts, it may be useful to scan through a ring buffer that may
21*61c4878aSAndroid Build Coastguard Workerhave a mix of valid (yet to be read), stale (read), and invalid entries. The
22*61c4878aSAndroid Build Coastguard Worker``PrefixedEntryRingBufferMulti::iterator`` class can be used to walk through
23*61c4878aSAndroid Build Coastguard Workerentries in the provided buffer.
24*61c4878aSAndroid Build Coastguard Worker
25*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
26*61c4878aSAndroid Build Coastguard Worker
27*61c4878aSAndroid Build Coastguard Worker   // A test string to push into the buffer.
28*61c4878aSAndroid Build Coastguard Worker   constexpr char kExampleEntry[] = "Example!";
29*61c4878aSAndroid Build Coastguard Worker
30*61c4878aSAndroid Build Coastguard Worker   // Setting up buffers and attaching a reader.
31*61c4878aSAndroid Build Coastguard Worker   std::byte buffer[1024];
32*61c4878aSAndroid Build Coastguard Worker   std::byte read_buffer[256];
33*61c4878aSAndroid Build Coastguard Worker   PrefixedEntryRingBuffer ring_buffer;
34*61c4878aSAndroid Build Coastguard Worker   PrefixedEntryRingBuffer::Reader reader;
35*61c4878aSAndroid Build Coastguard Worker   ring_buffer.SetBuffer(buffer);
36*61c4878aSAndroid Build Coastguard Worker   ring_buffer.AttachReader(reader);
37*61c4878aSAndroid Build Coastguard Worker
38*61c4878aSAndroid Build Coastguard Worker   // Insert some entries and process some entries.
39*61c4878aSAndroid Build Coastguard Worker   ring_buffer.PushBack(kExampleEntry);
40*61c4878aSAndroid Build Coastguard Worker   ring_buffer.PushBack(kExampleEntry);
41*61c4878aSAndroid Build Coastguard Worker   reader.PopFront();
42*61c4878aSAndroid Build Coastguard Worker
43*61c4878aSAndroid Build Coastguard Worker   // !! A function causes a crash before we've read out all entries.
44*61c4878aSAndroid Build Coastguard Worker   FunctionThatCrashes();
45*61c4878aSAndroid Build Coastguard Worker
46*61c4878aSAndroid Build Coastguard Worker   // ... Crash Context ...
47*61c4878aSAndroid Build Coastguard Worker
48*61c4878aSAndroid Build Coastguard Worker   // You can use a range-based for-loop to walk through all entries.
49*61c4878aSAndroid Build Coastguard Worker   for (auto entry : ring_buffer) {
50*61c4878aSAndroid Build Coastguard Worker     PW_LOG_WARN("Read entry of size: %u",
51*61c4878aSAndroid Build Coastguard Worker                 static_cast<unsigned>(entry.buffer.size()));
52*61c4878aSAndroid Build Coastguard Worker   }
53*61c4878aSAndroid Build Coastguard Worker
54*61c4878aSAndroid Build Coastguard WorkerIn cases where a crash has caused the ring buffer to have corrupted data, the
55*61c4878aSAndroid Build Coastguard Workeriterator will progress until it sees the corrupted section and instead move to
56*61c4878aSAndroid Build Coastguard Worker``iterator::end()``. The ``iterator::status()`` function returns a
57*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::Status` indicating the reason the iterator reached it's end.
58*61c4878aSAndroid Build Coastguard Worker
59*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp
60*61c4878aSAndroid Build Coastguard Worker
61*61c4878aSAndroid Build Coastguard Worker   // ... Crash Context ...
62*61c4878aSAndroid Build Coastguard Worker
63*61c4878aSAndroid Build Coastguard Worker   using iterator = PrefixedEntryRingBufferMulti::iterator;
64*61c4878aSAndroid Build Coastguard Worker
65*61c4878aSAndroid Build Coastguard Worker   // Hold the iterator outside any loops to inspect it later.
66*61c4878aSAndroid Build Coastguard Worker   iterator it = ring_buffer.begin();
67*61c4878aSAndroid Build Coastguard Worker   for (; it != it.end(); ++it) {
68*61c4878aSAndroid Build Coastguard Worker     PW_LOG_WARN("Read entry of size: %u",
69*61c4878aSAndroid Build Coastguard Worker                static_cast<unsigned>(it->buffer.size()));
70*61c4878aSAndroid Build Coastguard Worker   }
71*61c4878aSAndroid Build Coastguard Worker
72*61c4878aSAndroid Build Coastguard Worker   // Warn if there was a failure during iteration.
73*61c4878aSAndroid Build Coastguard Worker   if (!it.status().ok()) {
74*61c4878aSAndroid Build Coastguard Worker     PW_LOG_WARN("Iterator failed to read some entries!");
75*61c4878aSAndroid Build Coastguard Worker   }
76*61c4878aSAndroid Build Coastguard Worker
77*61c4878aSAndroid Build Coastguard WorkerData corruption
78*61c4878aSAndroid Build Coastguard Worker===============
79*61c4878aSAndroid Build Coastguard Worker``PrefixedEntryRingBufferMulti`` offers a circular ring buffer for arbitrary
80*61c4878aSAndroid Build Coastguard Workerlength data entries. Some metadata bytes are added at the beginning of each
81*61c4878aSAndroid Build Coastguard Workerentry to delimit the size of the entry. Unlike the iterator, the methods in
82*61c4878aSAndroid Build Coastguard Worker``PrefixedEntryRingBufferMulti`` require that data in the buffer is not corrupt.
83*61c4878aSAndroid Build Coastguard WorkerWhen these methods encounter data corruption, there is no generic way to
84*61c4878aSAndroid Build Coastguard Workerrecover, and thus, the application crashes. Data corruption is indicative of
85*61c4878aSAndroid Build Coastguard Workerother issues.
86