# Roadmap
Planned features and design sketches for future surelock versions. These are ideas that have been explored in design discussions but are not yet implemented.
## RwLock Support
A `RwLock<T, Lvl, R>` that participates in the same level ordering as `Mutex`. The main design challenge is that `Acquirable` and `LockSet` would need to express read vs write mode:
- A `LockSet` containing both a `Mutex` and an `RwLock` (read mode) at the same level
- The guard type changes depending on mode (`ReadGuard` vs `WriteGuard`)
- The `RawMutex` trait would need a `RawRwLock` counterpart (or the trait is extended)
One approach: `RwLock` implements `Acquirable` twice -- once for read mode, once for write. The user specifies mode at `LockSet` construction or via a wrapper type (`ReadLock(&rwlock)`, `WriteLock(&rwlock)`).
## Poisoning
A `Poisonable<T, Lvl, R>` wrapper type that detects panics during critical sections and flags the mutex as poisoned for subsequent acquirers.
The design is well-sketched: the wrapper implements `Acquirable<'a>` with `Guard = Result<PoisonGuard, PoisonError>`. `PoisonGuard`'s `Drop` checks `std::thread::panicking()`. Recovery via `PoisonError::into_inner()` (same as `std`).
Behind a `poisoning` feature flag that implies `std` (requires `std::thread::panicking()`). No mixing `Poisonable` and `Mutex` in one `LockSet`.
## Multi-Level `LockSet` for 3-12 Tuples
Currently, multi-level `LockSet` (mutexes at different levels in one set) is supported for 2-tuples only. The 3-12 tuple impls require same-level.
Extending to multi-level for higher arities requires recursive `MinLevel`/`MaxLevel` computation in `macro_rules!`, which is difficult because Rust macros can't easily generate `where` clause fragments that compose with other bounds. Possible approaches:
- Manual impls for common arities (3, 4)
- A proc macro (but we deliberately eliminated our proc macro crate)
- Accept same-level for 3+ and use key chaining for cross-level
The 2-tuple multi-level impl covers the most common case (two subsystems at different levels acquired atomically).
## `CriticalSectionRawMutex`
A zero-spin `RawMutex` backend for single-core bare-metal targets. Published as a separate crate (`surelock-cs` or `surelock-critical-section` or similar).
On single-core targets, surelock's ordering invariant guarantees that a lock is _always free_ when requested (circular wait is prevented and there's only one execution context). The "lock" operation doesn't need to spin or check -- it just disables interrupts (enters a critical section). "Unlock" re-enables them.
```rust
// surelock-cs crate (~30 lines)
pub struct CriticalSectionRawMutex;
unsafe impl surelock::raw_mutex::RawMutex for CriticalSectionRawMutex {
type Guard<'a> = CsGuard;
fn new() -> Self { Self }
fn lock(&self) -> Self::Guard<'_> {
let restore = unsafe { critical_section::acquire() };
CsGuard(restore)
}
fn try_lock(&self) -> Option<Self::Guard<'_>> {
Some(self.lock())
}
}
pub struct CsGuard(critical_section::RestoreState);
impl Drop for CsGuard {
fn drop(&mut self) {
unsafe { critical_section::release(self.0); }
}
}
```
User setup:
```toml
[dependencies]
surelock = { version = "0.1", default-features = false }
surelock-cs = "0.1"
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
```
```rust
type Mutex<T, Lvl = Base> = surelock::mutex::Mutex<T, Lvl, surelock_cs::CriticalSectionRawMutex>;
```
Why a separate crate:
- Surelock's purpose is deadlock prevention, not mutex implementation. `StdMutex` is in-crate because it's the default backend. Specialized backends belong in companion crates.
- Follows the `lock_api` ecosystem convention (backends are separate crates).
- Users who don't need it don't see it in the dependency tree.
- Can be maintained and released on a different cadence.
Value over `spin::Mutex` + `portable-atomic`:
- Zero spin: no CAS, no retry loop, no backoff. Just interrupt disable/enable.
- Smaller code size: no spin loop compiled in. Matters on flash-constrained targets (thumbv6m can have as little as 16KB flash).
- Eliminates spin dependency entirely for the lock path.
- Semantic clarity: the type encodes "this is single-core, locks are never contended."
> [!NOTE]
> `portable-atomic` is still needed for `LockId::fetch_add` and `Locksmith`'s atomics. `CriticalSectionRawMutex` only eliminates spin from the lock/unlock hot path.