ring-buffer-macro 0.2.0

A procedural macro for creating ring buffer (circular buffer) data structures at compile time
Documentation
# Changelog

All notable changes to this project will be documented in this file.

---

## [0.2.0]

Thread-safe ring buffers with lock-free SPSC, CAS-based MPSC, and new standard mode methods.

### Added

**SPSC mode** — lock-free single-producer/single-consumer:
```rust
#[ring_buffer(capacity = 1024, mode = "spsc")]
struct Queue(String);
```

Generated fields:
- `data: UnsafeCell<Vec<MaybeUninit<T>>>` — slot storage
- `head: AtomicUsize` — read position (Acquire/Release)
- `tail: AtomicUsize` — write position (Acquire/Release)
- `_marker: PhantomData<T>` — type marker

Generated methods:
- `new()` — creates empty SPSC buffer
- `split() → (Producer, Consumer)` — borrow-based producer/consumer handles
- `capacity() → usize` — maximum elements
- `len() → usize` — current count
- `is_empty() → bool` — check if empty
- `is_full() → bool` — check if full

Producer methods:
- `try_enqueue(item) → Result<(), T>` — non-blocking enqueue
- `is_full() → bool`
- `len() → usize`
- `is_empty() → bool`

Consumer methods:
- `try_dequeue() → Option<T>` — non-blocking dequeue
- `peek() → Option<&T>` — view front without removing
- `is_empty() → bool`
- `len() → usize`
- `is_full() → bool`

Thread safety:
- `unsafe impl Send + Sync` for buffer (where `T: Send`)
- `unsafe impl Send` for Producer and Consumer

**MPSC mode** — CAS-based multi-producer/single-consumer:
```rust
#[ring_buffer(capacity = 1024, mode = "mpsc")]
struct WorkQueue(Task);
```

Generated fields:
- `data: UnsafeCell<Vec<MaybeUninit<T>>>` — slot storage
- `written: Box<[AtomicBool]>` — per-slot write completion flags
- `head: AtomicUsize` — read position
- `tail: AtomicUsize` — write position (CAS-contended)
- `_marker: PhantomData<T>` — type marker

Generated methods:
- `new()` — creates empty MPSC buffer
- `producer() → Producer` — clonable producer handle
- `consumer() → Consumer` — single consumer handle
- `capacity() → usize` — maximum elements
- `len() → usize` — current count
- `is_empty() → bool` — check if empty

Producer methods (`Clone`):
- `try_enqueue(item) → Result<(), T>` — CAS-based enqueue with retry loop
- `is_full() → bool`

Consumer methods:
- `try_dequeue() → Option<T>` — waits for slot `written` flag via spin loop
- `peek() → Option<&T>` — view front without removing
- `is_empty() → bool`
- `len() → usize`

Thread safety:
- `unsafe impl Send + Sync` for buffer (where `T: Send`)
- `unsafe impl Send + Sync` for Producer
- `unsafe impl Send` for Consumer

**Standard mode — new methods:**
- `peek() → Option<&T>` — view front item without removing
- `peek_mut() → Option<&mut T>` — mutable reference to front item
- `peek_back() → Option<&T>` — view most recently added item
- `iter() → impl Iterator<Item = &T>` — iterate by reference, head to tail
- `drain() → Drain<T>` — consuming iterator, cleans up remaining elements on drop

**Named parameter syntax:**
```rust
#[ring_buffer(capacity = 10, mode = "standard", power_of_two = false)]
```

**Configuration options:**
- `mode``"standard"` (default), `"spsc"`, or `"mpsc"`
- `power_of_two` — replaces `index % capacity` with `index & (capacity - 1)`. Compile-time error if capacity is not a power of two
- `cache_padded` — wraps head/tail in `#[repr(C, align(64))]` wrapper types to prevent false sharing
- `blocking` — adds `Mutex<()>` + `Condvar` fields, enables blocking methods on SPSC/MPSC handles

**Blocking operations** (SPSC & MPSC, when `blocking = true`):
- `enqueue_blocking(item)` — blocks on `Condvar` until space is available
- `dequeue_blocking() → T` — blocks on `Condvar` until an item is ready

**Spin-wait hints** — all concurrent retry loops use `std::hint::spin_loop()`

### No Breaking Changes

The simple `#[ring_buffer(N)]` syntax still works. All new features are opt-in.

---

## [0.1.0]

Initial release of ring-buffer-macro. Single-threaded compile-time ring buffer.

```rust
#[ring_buffer(8)]
struct Buffer(i32);
```

Generated fields:
- `data: Vec<T>` — backing storage
- `capacity: usize` — maximum elements
- `head: usize` — read position
- `tail: usize` — write position
- `size: usize` — current count

Generated methods:
- `new() → Self` — creates empty buffer with `Vec::with_capacity(N)`
- `enqueue(item) → Result<(), T>` — push to tail, returns `Err(item)` if full
- `dequeue() → Option<T>` — pop from head, returns `None` if empty (requires `T: Clone`)
- `is_full() → bool` — check if `size == capacity`
- `is_empty() → bool` — check if `size == 0`
- `len() → usize` — current element count
- `capacity() → usize` — maximum capacity
- `clear()` — reset head, tail, and size to 0