Challenges 10.1 to 10.3 isolated ownership, allocation, and threading. This capstone assembles them into a small application: read a binary telemetry stream, validate records, aggregate statistics, and emit a deterministic text summary. Treat it as a portfolio piece that demonstrates systems habits, not a single-file homework snippet.
Recommended build order
- Single-threaded parser with
std::span<const std::byte>andstd::expected(Lessons 3.6, 6.7, 8.5). Lock correctness with unit tests before any threads exist.
- Aggregation logic as pure functions over parsed records, easy to test without I/O.
- Bounded queue from 10.3 (or your own) with an explicit shutdown signal so workers exit cleanly.
- CMake targets separating library, executable, and tests (Lessons 0.4, 8.1, 8.8).
- Sanitizers and one benchmark (Lessons 0.4, 8.9) only after correctness is proven.
Architecture sketch
- Input: file or stdin → read into a byte buffer or memory-mapped region.
- Parser:
parseRecord(span)→expected<Record, ParseError>; never read pastspan.size().
- Workers (optional phase): producer threads parse chunks; consumers aggregate into thread-safe accumulators or per-thread locals merged at the end.
- Output: deterministic summary (count, min, max, mean) written to stdout or a report file.
Requirements
- Interface design: parsing through
std::span<const std::byte>withstd::expected<Record, ParseError>(C++23).
- Ownership: no raw owning pointers; values, containers, and RAII throughout.
- Concurrency: bounded queue plus shutdown that wakes blocked threads.
- Build: library target, executable, and test targets in CMake.
- Quality gate: unit tests; ASan/UBSan builds; TSan on the queue where supported.
Suggested repository shape
Acceptance checklist
- Malformed input returns a descriptive error without reading past the span.
- A fixed fixture yields exact count, min, max, and average.
- Queue shutdown wakes blocked producers and consumers.
ctest --test-dir buildpasses.
- A benchmark documents compiler flags, hardware, hypothesis, result, and limitations.
Measurement discipline
Name one hypothesis before benchmarking, for example, batching 64 records per queue push reduces mutex traffic. Compare against a baseline on the same machine and build flags. Lesson 0.4 lists sanitizer versus perf roles; do not conflate them.
Stretch goals: little- and big-endian fixtures (Lesson 3.6), std::jthread stop-token shutdown test, std::pmr arena only if benchmarks justify the complexity.