Skip to content

kithara ring

Pavel Litvinenko edited this page Sep 23, 2026 · 1 revision

kithara-ring

Contract reviewed from PR #428, source revision 8fc1af7cf. This records that branch contract, not merged release status or new runtime validation. API and usage · All crates.

Ownership

This crate owns one mechanism: a lock-free single-producer single-consumer ring whose slots live in memory someone else owns. It implements ringbuf::Storage for OwnedSlice<B>, where B is any owner that dereferences mutably to [T] with T: Copy, and split turns such an owner into the producer and consumer halves of an ordinary ringbuf::SharedRb.

The crate knows nothing about pools, budgets, or audio. kithara-bufpool extends it with PoolRegion::ring, which hands it a pooled buffer; any other owner of a contiguous slice works the same way. Push and pop are unchanged ringbuf code, so the ring behaves exactly like a heap-backed one apart from where its slots come from.

All unsafe code for storage over a foreign owner is confined here and runs under Miri (just test miri); crates that use the ring, including kithara-bufpool, keep forbid(unsafe_code).

Lifetime contract

  • split moves the owner behind its own allocation and takes the slot pointer and length once. The owner is not touched again until the storage drops, so the pointer stays valid whether the slice is inline in the owner or on the heap. That allocation is one Box of the owner's size per ring, made at creation and never on the push/pop path.
  • The ring's capacity is the slice length. Every slot starts vacant: values already in the owner's slice are never observed, only overwritten.
  • The owner drops exactly once, after both halves are gone. Its own drop logic releases the memory; for a pooled buffer that returns it to the pool, so a consumer that outlives its producer keeps the budget charged until it drops.
  • An empty slice cannot hold a ring. split returns the unchanged owner as the error, and PoolRegion::ring maps that to PoolError::EmptyRing.

Element contract

T: Copy is required, not incidental. ringbuf treats slots as uninitialised and drops popped values itself, while the owner also believes it holds initialised values; a type with drop glue would be dropped twice. Copy removes drop glue, so the two views never disagree.

Send and Sync hold when the owner is Send and T is Send: only the slots are shared, and the single-producer single-consumer protocol keeps the halves on disjoint ranges.

Clone this wiki locally