Shared Container
Type-safe shared data access for multi-threaded, async, and single-threaded environments.
Overview
shared-container provides type-safe abstractions for shared data access across different runtime environments:
- Synchronous multi-threaded:
Arc<RwLock<T>>on native platforms - Single-threaded (WebAssembly):
Rc<RefCell<T>> - Asynchronous (Tokio):
Arc<tokio::sync::RwLock<T>>
Version 0.3 introduces type-level separation between sync and async, eliminating runtime surprises and providing explicit error handling.
Key Features
- Type-Level Safety: Separate types for sync (
Shared<T>) and async (AsyncShared<T>) - Platform-Aware: Automatically selects the right backend based on target
- Explicit Errors:
Result<_, AccessError>instead ofOptionor panics - Zero Runtime Overhead: No blocking operations or runtime initialization
- Weak References: Break reference cycles with weak pointers
Quick Start
Add this to your Cargo.toml:
[]
= "0.3"
Synchronous Usage
use ;
// Create a new container
let container = new;
// Read access
let guard = container.read.unwrap;
assert_eq!;
drop;
// Write access
let mut guard = container.write.unwrap;
* guard = 100;
drop;
// Clone the container (both point to the same data)
let container2 = container.clone;
// Get a cloned value
let value = container.get_cloned.unwrap;
assert_eq!;
Asynchronous Usage
Enable the async feature:
[]
= { = "0.3.0", = ["async"] }
use ;
async
Working with Custom Types
use ;
let container = new;
// Modify the user
let mut guard = container.write.unwrap;
guard.name = "Bob".to_string;
drop;
// Get a snapshot
let user_snapshot = container.get_cloned.unwrap;
println!;
Weak References
use ;
let container = new;
let weak = container.downgrade;
// Try to upgrade
if let Some = weak.upgrade else
// After dropping all strong references
drop;
assert!;
Error Handling
The new API uses AccessError enum for explicit error handling:
use ;
let container = new;
match container.read
Error Types
Poisoned: Lock was poisoned by a panic (multi-threaded only)BorrowConflict: Borrow rules violated (WebAssemblyRefCellonly)UnsupportedMode: Operation not supported for this container type
Universal Container (Advanced)
For generic code that needs to work with both sync and async containers:
use ;
let sync_container: = new.into;
process_container;
Platform-Specific Behavior
| Platform | Backend | Notes |
|---|---|---|
| Native (multi-threaded) | Arc<std::sync::RwLock<T>> |
Can be poisoned by panics |
| WebAssembly | Rc<RefCell<T>> |
Borrow checking at runtime |
| Async (Tokio) | Arc<tokio::sync::RwLock<T>> |
Requires async feature |
Feature Flags
async: EnablesAsyncShared<T>and async trait methods (requires tokio)std-sync(default): Legacy support forSharedContainerwith std sync primitivestokio-sync: Legacy support forSharedContainerwith tokio primitives (deprecated)wasm-sync: Legacy support for forcing WebAssembly backend
Migration from 2.x
Version 0.3 introduces breaking changes with a clearer, type-safe API. The old SharedContainer<T> is deprecated but
still available.
Migration Guide
| Old (0.2.x) | New (0.3.x) |
|---|---|
SharedContainer::new(v) (std-sync) |
Shared::new(v) |
SharedContainer::new(v) (tokio-sync) |
AsyncShared::new(v) with async feature |
container.read() → Option<Guard> |
container.read() → Result<Guard, AccessError> |
container.write() → Option<Guard> |
container.write() → Result<Guard, AccessError> |
container.read_async().await |
container.read_async().await (same) |
Example Migration
Before (0.2.x):
use SharedContainer;
let container = new;
if let Some = container.read
After (0.3.x):
use ;
let container = new;
match container.read
For async code with tokio:
Before (0.2.x with tokio-sync):
use SharedContainer;
let container = new;
let guard = container.read_async.await;
After (0.3.x with async feature):
use ;
let container = new;
let guard = container.read_async.await;
Testing
# Run all tests with default features
# Run tests with async support
# Run all tests
License
This project is licensed under the MIT License - see the LICENSE file for details.