atomic_refcell

A thread-safe analogue of RefCell for Rust with runtime borrow checking

Library
Cargo
v0.1.14
102stars
Apache-2.0 OR MIT

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
39/100Needs Attention
Development Activity12
Maintenance0
Community72
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
83/100Excellent
Architecture85
Code Quality88
Innovation78
Learning Curve80

atomic_refcell is a small, no_std-compatible Rust crate that brings RefCell-style borrow semantics to values shared across threads. It offers runtime-checked immutable and mutable borrows backed by a single atomic reference count, making it a lighter-weight alternative to RwLock for cases where you can guarantee mutable and immutable borrows never overlap concurrently.

Because it uses just one atomic operation per borrow rather than the multiple atomics a read-write lock needs, AtomicRefCell keeps immutable borrows cheap and supports useful ergonomics like mapping references (AtomicRef::map) that a lock-based design cannot. The implementation carefully handles panics on illegal borrows so that a misuse on one thread never causes undefined behavior on others.

What You Get

  • AtomicRefCell<T>, a thread-safe (Sync) cell with RefCell-like borrow semantics
  • Runtime-checked borrow() / borrow_mut() plus fallible try_borrow() / try_borrow_mut() variants
  • AtomicRef and AtomicRefMut guards with map() support for projecting into fields
  • no_std compatibility and optional serde and portable-atomic feature flags

Common Use Cases

  • Sharing mutable state across threads where borrows are known never to overlap concurrently
  • Replacing RwLock in hot paths to avoid the cost of multiple atomic operations per immutable borrow
  • Building Sync data structures on embedded or no_std targets via the portable-atomic feature
  • Serializing and deserializing shared cell contents with the optional serde feature

Under The Hood

Architecture - The entire crate lives in a single src/lib.rs (~560 lines) that reimplements RefCell semantics from scratch around a single AtomicUsize counter inside an UnsafeCell<T>. The high bit of the counter encodes a mutable borrow (set via compare-and-swap when the count is zero) while lower bits count immutable borrows via atomic increment; conflicting access panics and mutable release resets the counter to zero, clearing any stray increments left by panicked threads. AtomicRef and AtomicRefMut RAII guards decrement/reset on drop, and both expose map() for reference projection.

Tech Stack - Pure Rust, edition 2021, MSRV 1.60, with zero required runtime dependencies. Optional dependencies are gated behind feature flags: serde (Serialize/Deserialize impls) and portable-atomic (for targets without native compare-and-swap). serde_json is a dev-dependency used only by tests.

Code Quality - The concurrency-critical logic is deliberately segmented and heavily commented to keep the unsafe core small and auditable, with #![deny(missing_docs)] enforcing documentation on the public API. Tests live in tests/basic.rs (~205 lines) and tests/async.rs, covering borrow rules, panic behavior, and async usage. The code is mature and stable, derived by adapting the standard library’s RefCell implementation.

API Design - The public surface mirrors std::cell::RefCell almost exactly (new, borrow, borrow_mut, try_borrow, try_borrow_mut), so Rust developers need no new mental model; the only additions are thread-safety and guard map(). Getting started requires no configuration, and the README concisely documents features and the borrow-invariant contract callers must uphold.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search