Skip to content

Commit ad92db6

Browse files
committed
Document complete C and C++ API reference and future work in README.
Adds v0.2 API completeness summary, full container key-API tables, C API reference, examples index, and explicit future-work backlog for v0.2.1.
1 parent e0d680d commit ad92db6

1 file changed

Lines changed: 118 additions & 40 deletions

File tree

README.md

Lines changed: 118 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,20 @@ C++ Ring<T>, Vector<T>, … → detail/*_core<Policy> ← c_api/*_box →
5656
5757
**C++ (32 utilities)** — templates and header-only classes in `include/memkit/containers/`, included via `<memkit/memkit.hpp>`.
5858
59-
**C (14 containers)** — type-erased by design (C23 has no generics). Each container exposes `*_init` / `*_create` / `*_destroy` over a shared `*_box` implementation. Utility types (`SmallString`, `SmallBuffer`, queues, maps, `FixedVariant`, `TokenBucket`, `FixedIoVec`, `LookupTable`, etc.) are C++-only.
59+
**C (14 containers + arena)** — type-erased by design (C23 has no generics). Each container exposes `*_init` / `*_create` / `*_destroy` over a shared `*_box` implementation. Utility types (`SmallString`, `SmallBuffer`, queues, maps, `FixedVariant`, `TokenBucket`, `FixedIoVec`, `LookupTable`, etc.) are **C++-only** by design.
60+
61+
### API completeness (v0.2)
62+
63+
The public API is **feature-complete** for embedded use on Unix (macOS and Linux). Every shipped container is listed in the [C++ API reference](#c-api) and [C API reference](#c-api-1) below; authoritative signatures live in the headers.
64+
65+
| Surface | Count | MCU | MPU | Notes |
66+
|---------|-------|-----|-----|-------|
67+
| C++ utilities | 32 | all | all | `#include <memkit/memkit.hpp>` |
68+
| C containers | 14 | tier 1 (8) | tier 1 + tier 2 (14) | `#include <memkit.h>` or per-container `*.h` |
69+
| C arena | 1 | yes | yes | Bump allocator; mmap/heap create on MPU |
70+
| C++-only helpers | 18 | yes | yes | No C bindings (see [cheat sheet](#container-cheat-sheet)) |
71+
72+
**Tests:** 31 C++ test binaries cover all 32 C++ containers (`Stack` and `Queue` share `test_stack_queue_cpp.cpp`). C API coverage is `test_c_api_smoke.c` (tier 1, MCU) and `test_c_api_extended.c` (tier 1 + tier 2 + create paths, MPU).
6073
6174
Pick the API that fits your project:
6275
@@ -139,45 +152,47 @@ Include the umbrella header:
139152

140153
All containers live in namespace `memkit`. Operations return `memkit::status`; use `memkit::ok(st)` to test success.
141154

142-
### Containers
143-
144-
| Class | Header (via memkit.hpp) | Role |
145-
|-------|-------------------------|------|
146-
| `Ring<T>` | `containers/ring.hpp` | Circular buffer; optional overwrite-on-full |
147-
| `Queue<T>` | `containers/queue.hpp` | FIFO ring |
148-
| `Deque<T>` | `containers/deque.hpp` | Double-ended ring |
149-
| `Vector<T>` | `containers/vector.hpp` | Contiguous array; optional growable |
150-
| `Stack<T>` | `containers/stack.hpp` | LIFO (vector core) |
151-
| `Bitset` | `containers/bitset.hpp` | Fixed bit set |
152-
| `ObjPool<T>` | `containers/objpool.hpp` | Fixed-size object pool |
153-
| `HashMap<K,V>` | `containers/hashmap.hpp` | Hash map (chaining or open addressing) |
154-
| `BTree<K,V>` | `containers/btree.hpp` | Ordered map |
155-
| `PQueue<T,Compare>` | `containers/pqueue.hpp` | Binary heap priority queue |
156-
| `List<T>` | `containers/list.hpp` | Singly linked list |
157-
| `DList<T>` | `containers/dlist.hpp` | Doubly linked list |
158-
| `LruCache<K,V>` | `containers/lrucache.hpp` | LRU cache |
159-
| `HandlePool<T>` | `containers/handle_pool.hpp` | Generation-based stable handles |
160-
| `SmallString<N>` | `containers/small_string.hpp` | Fixed-capacity string (no heap) |
161-
| `ByteRing` | `containers/byte_ring.hpp` | Byte stream ring for UART/DMA I/O |
162-
| `IntrusiveListHead` | `containers/intrusive_list.hpp` | Intrusive singly/dlist heads (zero allocation) |
163-
| `SpscQueue<T>` | `containers/spsc_queue.hpp` | Lock-free single-producer/single-consumer queue |
164-
| `FlatMap<K,V>` | `containers/flat_map.hpp` | Sorted flat array map for tiny key sets |
165-
| `TimerWheel<N>` | `containers/timer_wheel.hpp` | Hashed timing wheel for deferred callbacks |
166-
| `DoubleBuffer<T>` | `containers/double_buffer.hpp` | Ping-pong buffer for DMA/ADC/audio |
167-
| `MpscQueue<T>` | `containers/mpsc_queue.hpp` | Bounded multi-producer single-consumer queue |
168-
| `EnumMap<Enum,V,N>` | `containers/enum_map.hpp` | O(1) enum-keyed map |
169-
| `RingLog<Record>` | `containers/ring_log.hpp` | Flight-recorder circular log (overwrite oldest) |
170-
| `SparseSet` | `containers/sparse_set.hpp` | O(1) active-ID set with dense iteration |
171-
| `SmallBuffer<N>` | `containers/small_buffer.hpp` | Length-prefixed binary payload buffer |
172-
| `FixedVariant<Ts...>` | `containers/fixed_variant.hpp` | Fixed-storage tagged union |
173-
| `TokenBucket` | `containers/token_bucket.hpp` | Tick-based rate limiter |
174-
| `FixedIoVec<N>` | `containers/fixed_iovec.hpp` | Fixed scatter/gather slice list for DMA |
175-
| `LookupTable<X,Y>` | `containers/lookup_table.hpp` | Sorted calibration table with interpolation |
176-
| `BitReader` / `BitWriter` | `containers/bit_stream.hpp` | MSB-first packed bit I/O |
177-
| `MovingAverage<T,N>` | `containers/running_stats.hpp` | Fixed-window moving average |
178-
| `WindowStats<T,N>` | `containers/running_stats.hpp` | Fixed-window min/max/average |
179-
180-
Memory helpers: `memkit::memory::static_arena`, `fixed_buffer`, `fixed_pool`, and on MPU `heap_arena`, `mmap_arena`, `mmap_storage`.
155+
### Containers (complete)
156+
157+
All types live in namespace `memkit`. Operations return `memkit::status` unless noted. Every class supports `init` from caller storage; most also support `init_from_arena`. Move-only; destructors call `clear()`.
158+
159+
| Class | Header | Role | Key API |
160+
|-------|--------|------|---------|
161+
| `Ring<T>` | `ring.hpp` | Circular buffer | `init`, `init_from_arena`, `push_back`/`front`, `pop_*`, `try_*`, `readable_contiguous`, `writable_contiguous`, `commit_read`/`write`, `ring_policy` |
162+
| `Queue<T>` | `queue.hpp` | FIFO ring | `init`, `init_from_arena`, `push_back`, `pop_front`, `peek_*`, `queue_policy` |
163+
| `Deque<T>` | `deque.hpp` | Double-ended ring | `init`, `init_from_arena`, `push_back`/`front`, `pop_*`, `peek_*`, `deque_policy` |
164+
| `Vector<T>` | `vector.hpp` | Contiguous array | `init`, `init_from_arena`, `push_back`, `pop_back`, `peek_at`, `set_at`, `at`, `reserve`, `vector_policy` |
165+
| `Stack<T>` | `stack.hpp` | LIFO (vector core) | `init`, `init_from_arena`, `push`, `pop`, `peek`, `stack_policy` |
166+
| `Bitset` | `bitset.hpp` | Fixed bit set | `init`, `init_from_arena`, `set`/`reset`/`test`/`toggle`, `find_first_*`, `union_with`, `intersect_with`, `load_bytes`/`store_bytes` |
167+
| `ObjPool<T>` | `objpool.hpp` | Object pool | `init`, `init_from_arena`, `alloc`, `free`, `contains` |
168+
| `HashMap<K,V>` | `hashmap.hpp` | Hash map | `init`, `init_from_arena`, `put`, `get`, `remove`, `contains`, `foreach`, `hashmap_strategy`, `hashmap_policy` |
169+
| `BTree<K,V>` | `btree.hpp` | Ordered map | `init`, `init_from_arena`, `insert`, `get`, `remove`, `contains`, `peek_min`/`max`, `foreach` |
170+
| `PQueue<T,Compare>` | `pqueue.hpp` | Binary heap | `init`, `init_from_arena`, `push`, `pop`, `peek`, `pqueue_policy` |
171+
| `List<T>` | `list.hpp` | Singly linked list | `init`, `init_from_arena`, `push_*`, `pop_*`, `insert_at`, `remove_at`, `foreach` |
172+
| `DList<T>` | `dlist.hpp` | Doubly linked list | Same as `List` plus `pop_back`, `foreach_reverse`, `front`/`back` pointers |
173+
| `LruCache<K,V>` | `lrucache.hpp` | LRU cache | `init`, `init_from_arena`, `get`, `put`, `remove`, `touch`, `contains`, `foreach_mru`/`lru` |
174+
| `HandlePool<T>` | `handle_pool.hpp` | Stable handles | `init`, `init_from_arena`, `acquire`, `release`, `valid`, `get`, `handle_t` |
175+
| `SmallString<N>` | `small_string.hpp` | Fixed string | `assign`, `append`, `clear`, `size`, `empty`, `view`, `c_str`, `operator==` |
176+
| `ByteRing` | `byte_ring.hpp` | Byte I/O ring | `init`, `init_from_arena`, `push_bytes`, `readable_contiguous`, `writable_contiguous`, `commit_read`/`write` |
177+
| `IntrusiveListHead` | `intrusive_list.hpp` | Intrusive lists | `push_back`/`front`, `erase`, `splice`, `is_linked`; hooks: `IntrusiveListHook`, `IntrusiveDListHook` |
178+
| `SpscQueue<T>` | `spsc_queue.hpp` | Lock-free SPSC | `init`, `init_from_arena`, `storage_bytes`, `push`, `pop`, `empty`, `full`, `size` |
179+
| `FlatMap<K,V>` | `flat_map.hpp` | Sorted flat map | `init`, `init_from_arena`, `put`, `get`, `remove`, `contains`, `find`, `foreach` |
180+
| `TimerWheel<N>` | `timer_wheel.hpp` | Timing wheel | `init`, `schedule`, `cancel`, `tick`; nodes: `TimerWheelNode` |
181+
| `DoubleBuffer<T>` | `double_buffer.hpp` | Ping-pong buffer | `init`, `init_from_arena`, `write_span`, `publish`, `read_span` |
182+
| `MpscQueue<T>` | `mpsc_queue.hpp` | Bounded MPSC | `init`, `init_from_arena`, `storage_bytes`, `storage_align`, `push`, `pop`, `empty`, `full`, `size` |
183+
| `EnumMap<Enum,V,N>` | `enum_map.hpp` | Enum map | `init`, `put`, `get`, `at`, `contains`, `clear`, `foreach` |
184+
| `RingLog<Record>` | `ring_log.hpp` | Flight recorder | `init`, `init_from_arena`, `append`, `clear`, `size`, `capacity`, `foreach` |
185+
| `SparseSet` | `sparse_set.hpp` | Active ID set | `init`, `init_from_arena`, `insert`, `remove`, `contains`, `clear`, dense `operator[]` |
186+
| `SmallBuffer<N>` | `small_buffer.hpp` | Binary payload | `assign`, `clear`, `size`, `capacity`, `empty`, `data`, `span` |
187+
| `FixedVariant<Ts...>` | `fixed_variant.hpp` | Tagged union | `emplace`, `holds`, `get`, `destroy`, `index` |
188+
| `TokenBucket` | `token_bucket.hpp` | Rate limiter | `init`, `try_consume`, `consume`, `refill`, `reset`, `tokens` |
189+
| `FixedIoVec<N>` | `fixed_iovec.hpp` | Scatter/gather | `push`, `clear`, `size`, `empty`, `slice`, `span` |
190+
| `LookupTable<X,Y>` | `lookup_table.hpp` | Calibration table | `init`, `at`, `lookup` (interpolate), `size` |
191+
| `BitReader` / `BitWriter` | `bit_stream.hpp` | Packed bits | `read`/`write`, `read_bits`/`write_bits`, `flush`, `reset` |
192+
| `MovingAverage<T,N>` | `running_stats.hpp` | Moving average | `push`, `average`, `clear`, `empty`, `full` |
193+
| `WindowStats<T,N>` | `running_stats.hpp` | Window stats | `push`, `min`, `max`, `average`, `clear` |
194+
195+
**Memory helpers** (`memkit/memory/`): `fixed_buffer`, `static_arena`, `fixed_pool`; on MPU also `heap_arena`, `mmap_arena`, `mmap_storage`, `heap_storage`.
181196

182197
Type aliases: `memkit::Arena<…>`, `memkit::FixedPool<…>`.
183198

@@ -443,6 +458,46 @@ Controlled by `MEMKIT_C_API_FULL` and `MEMKIT_C_API_EXTENDED` in `memkit_config.
443458

444459
On MCU firmware that needs tier-2 containers, use the C++ API (`memkit.hpp`) with static or arena storage instead of the C stubs.
445460

461+
### Complete C API reference
462+
463+
Every C container follows the same conventions: `<name>_status_t`, `<name>_config_t`, opaque `<name>_t` blob, `<name>_init` / `<name>_create` / `<name>_deinit` / `<name>_destroy`, and `<name>_status_ok()`. Element types are passed as `void *` with `elem_size` (and optional copy/destroy callbacks).
464+
465+
**Arena** (`arena.h`) — tier 1, all targets
466+
467+
| Function | Purpose |
468+
|----------|---------|
469+
| `arena_init`, `arena_deinit` | Embed arena over caller buffer |
470+
| `arena_create`, `arena_create_with_backing`, `arena_destroy` | MPU: heap or mmap backing |
471+
| `arena_reset` | Free all bump allocations |
472+
| `arena_alloc`, `arena_calloc` | Aligned bump allocation (absolute pointer alignment) |
473+
| `arena_stats` | Capacity / used / remaining |
474+
475+
**Tier 1 containers** — MCU + MPU
476+
477+
| Container | Header | Key functions |
478+
|-----------|--------|---------------|
479+
| Ring | `ring.h` | `push_back`/`front`, `pop_*`, `peek_*`, `set_at`, `foreach`, `readable_contiguous`, `writable_contiguous`, `commit_read`/`write` |
480+
| Queue | `queue.h` | `push`, `pop`, `peek_*`, `foreach`, contiguous + commit (same as ring) |
481+
| Vector | `vector.h` | `reserve`, `push_back`, `pop_back`, `peek_*`, `set_at`, `at`, `foreach` |
482+
| Stack | `stack.h` | `push`, `pop`, `peek`, `foreach` |
483+
| Bitset | `bitset.h` | `set`/`reset`/`test`/`toggle`, `set_all`, `find_first_*`, `union_with`, `intersect_with`, `xor_with`, `complement`, `load_bytes`/`store_bytes`, `foreach` |
484+
| ObjPool | `objpool.h` | `alloc`, `free`, `contains`, `foreach` |
485+
| HandlePool | `handle_pool.h` | `acquire`, `release`, `valid`, `get`, `handle_t`, storage sizing helpers |
486+
487+
**Tier 2 containers** — MPU full; MCU stubs return `*_ERR_UNSUPPORTED`
488+
489+
| Container | Header | Key functions |
490+
|-----------|--------|---------------|
491+
| Deque | `deque.h` | `push_back`/`front`, `pop_*`, `peek_*`, `foreach`, contiguous + commit |
492+
| HashMap | `hashmap.h` | `put`, `get`, `remove`, `contains`, `foreach`; `hash_fn`, `key_eq_fn`; chaining or open addressing |
493+
| BTree | `btree.h` | `insert`, `get`, `remove`, `contains`, `peek_min`/`max`, `foreach`; `compare_fn` |
494+
| PQueue | `pqueue.h` | `push`, `pop`, `peek`, `foreach`; `compare_fn` |
495+
| List | `list.h` | `push_*`, `pop_*`, `peek_at`, `insert_at`, `remove_at`, `remove_first`, `front`, `foreach` |
496+
| DList | `dlist.h` | Same as list plus `back`, `foreach_reverse` |
497+
| LruCache | `lrucache.h` | `get`, `put`, `remove`, `contains`, `touch`, `peek`, `foreach_mru`/`lru`; key/value callbacks |
498+
499+
**Umbrella header:** `#include <memkit.h>` pulls `memkit_config.h` and all container headers above.
500+
446501
### Opaque objects
447502

448503
Each container handle embeds implementation storage:
@@ -713,3 +768,26 @@ memkit is intentionally slightly slower than a one-off C ring — you trade a fe
713768
---
714769

715770
## Examples (MCU)
771+
772+
| Example | Language | Demonstrates |
773+
|---------|----------|--------------|
774+
| `example_mcu.cpp` | C++ | Static ring + arena-backed ring |
775+
| `example_mcu_c.c` | C | Tier-1 ring + queue with caller storage |
776+
| `example_embedded_patterns.cpp` | C++ | DoubleBuffer, MpscQueue, LookupTable, bit stream, MovingAverage |
777+
| `example_comm_pipeline.cpp` | C++ | ByteRing RX, SpscQueue, TokenBucket pacing |
778+
779+
MPU examples: `example_mpu.cpp` (C++ mmap arena), `example_mpu.c` (C arena create + tier-2 create helpers). Built with `make mpu`.
780+
781+
---
782+
783+
## Future work
784+
785+
Not required for the current v0.2 feature set; possible follow-ups if demand appears:
786+
787+
| Area | Description |
788+
|------|-------------|
789+
| **Windows support** | `VirtualAlloc`/`VirtualFree` for the mmap arena path, MSVC/clang-cl CI, and CMake-first host builds. Core MCU containers are already portable; the gap is MPU optional backing and toolchain plumbing. |
790+
| **Exhaustive unit / fuzz / concurrency tests** | Today’s 31 C++ tests are happy-path smoke/integration coverage. Deeper work would add multi-threaded MPSC/SPSC stress tests, systematic error-path cases, and fuzz/property tests. |
791+
| **Per-container C API test parity** | C++ has one test file per container (except shared stack/queue). C has `test_c_api_smoke.c` + `test_c_api_extended.c` integration tests only — not dedicated per-header unit tests matching the C++ matrix. |
792+
793+
---

0 commit comments

Comments
 (0)