Ready for publish
This commit is contained in:
@@ -2,5 +2,8 @@
|
|||||||
name = "access-cell"
|
name = "access-cell"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
description = "A cell that allows **re-entrant mutable access** without deadlock"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
repository = "https://github.com/selimaj-dev/access-cell"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@@ -1,19 +1,58 @@
|
|||||||
# access-cell
|
# access-cell
|
||||||
A synchronous, single-threaded Mutex<T> anti-locking system
|
|
||||||
|
A cell that allows **re-entrant mutable access** without deadlock. Use it when you need something like a single-threaded “Mutex” where callbacks might need to access the same value again.
|
||||||
|
|
||||||
|
## Why?
|
||||||
|
|
||||||
|
With a normal `Mutex<T>`, if you lock it and then try to lock it again from the same thread (e.g. in a callback), you deadlock. `AccessCell<T>` avoids that: the first `access` runs immediately; any further `access` calls from inside that closure are **queued** and run in order after the current closure finishes.
|
||||||
|
|
||||||
|
So you can safely do “lock → do work → call something that also wants to lock” without re-entrancy causing a deadlock.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let value = Arc::new(AccessCell::new(0));
|
use access_cell::AccessCell;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
value.access({
|
let cell = Arc::new(AccessCell::new(0));
|
||||||
let value = value.clone();
|
|
||||||
|
|
||||||
|
cell.access({
|
||||||
|
let cell = cell.clone();
|
||||||
move |_| {
|
move |_| {
|
||||||
// normally this would cause a deadlock
|
// Nested access would deadlock with a Mutex, here it’s queued and runs after.
|
||||||
value.access(|v| {
|
cell.access(|v| {
|
||||||
*v = 10;
|
*v = 10;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(*value.access_ref(), 10);
|
assert_eq!(*cell.access_ref(), 10);
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
| Method | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `AccessCell::new(value)` | Create a new cell wrapping `value`. |
|
||||||
|
| `.access(\|v\| { ... })` | Run a closure with exclusive mutable access. Re-entrant calls are queued. |
|
||||||
|
| `.access_ref()` | Borrow the value immutably (safe to call anytime). |
|
||||||
|
| `.access_mut()` | **Unsafe** outside of an `access` closure. Use only inside a closure passed to `access`. |
|
||||||
|
|
||||||
|
## When to use it
|
||||||
|
|
||||||
|
- Single-threaded or “one logical owner” code where re-entrant access is possible (e.g. callbacks, event handlers).
|
||||||
|
- When you want “exclusive access” semantics without a real lock, and you’re okay with nested work being deferred to a queue.
|
||||||
|
|
||||||
|
Not a replacement for `Mutex` in multi-threaded code; it does not provide thread-safe locking.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
```bash
|
||||||
|
cargo add access-cell
|
||||||
|
```
|
||||||
|
|
||||||
|
Or manually
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[dependencies]
|
||||||
|
access-cell = "0.1"
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user