tspawn
tspawn is a Rust library that provides a thread-safe wrapper around Arc<RwLock<T>> with convenient cloning semantics and powerful async task spawning macros. It simplifies working with shared mutable state in concurrent and asynchronous Rust applications.
Features
- Thread-safe shared state: Built on
parking_lot::RwLockfor better performance thanstd::sync::RwLock - Convenient cloning: Clone the wrapper without explicit
Arc::clone()calls - Async task macros: Powerful
tspawn!macro for spawning tokio tasks with automatic cloning - Multiple access patterns: Support for read-only, write-only, and mixed access patterns
- No poisoning: Uses
parking_lotwhich doesn't have lock poisoning - Zero-cost abstractions: Minimal overhead over manual
Arc<RwLock<T>>usage
Installation
Add this to your Cargo.toml:
[]
= "0.1"
= { = "1.0", = ["full"] }
Quick Start
use ;
async
Core Types
A<T> - The Main Wrapper
A<T> is a thread-safe wrapper around Arc<RwLock<T>> that provides convenient methods for accessing and modifying shared data:
use A;
let data = new;
// Read access
let value = data.get; // Returns a clone of the inner value
let guard = data.read; // Returns a read guard
// Write access
data.set; // Set a new value
data.update; // Update using a closure
let mut guard = data.write; // Returns a write guard
The tspawn! Macro
The tspawn! macro simplifies spawning tokio tasks with shared state. It automatically clones the necessary data and provides different access patterns:
Single Variable Access
use ;
let data = new;
// Read-only access
tspawn!.await?;
// Write access
tspawn!.await?;
// Clone access (moves the cloned wrapper)
tspawn!.await?;
Multiple Variable Access
use ;
let x = new;
let y = new;
// Multiple read access
tspawn!.await?;
// Mixed access patterns
tspawn!.await?;
Complex Scenarios
use ;
let a = new;
let b = new;
let c = new;
// Three variables with mixed access
tspawn!.await?;
Advanced Usage
Working with Complex Types
use A;
use HashMap;
let users = new;
// Add a user
users.update;
// Read user data
if let Some = users.read.get
Integration with async/await
use ;
async
async
API Reference
A<T> Methods
new(value: T) -> Self- Create a new wrapperget() -> T- Get a clone of the inner value (requiresT: Clone)set(value: T)- Set a new valueupdate<F>(f: F)- Update the value using a closureread() -> RwLockReadGuard<'_, T>- Get a read guardwrite() -> RwLockWriteGuard<'_, T>- Get a write guardfrom_inner(Arc<RwLock<T>>) -> Self- Create from existing Arc<RwLock>into_inner(self) -> Arc<RwLock<T>>- Convert back to Arc<RwLock>
tspawn! Macro Variants
tspawn!(var, { code })- Clone the wrapper into the tasktspawn!(ref var, { code })- Read access within the tasktspawn!(mut var, { code })- Write access within the tasktspawn!(ref var1, ref var2, { code })- Multiple read accesstspawn!(mut var1, ref var2, { code })- Mixed access patterns- And more combinations for up to 3 variables
Performance
tspawn uses parking_lot::RwLock instead of std::sync::RwLock for better performance:
- Faster lock operations:
parking_lotis typically 2-3x faster - No poisoning overhead: Simpler error handling
- Better fairness: More predictable scheduling between readers and writers
- Smaller memory footprint: More efficient lock implementation
Examples
See the examples/ directory for more comprehensive examples:
Requirements
- Rust 1.70 or later
tokioruntime for async functionality
Contributing
We welcome contributions! Please feel free to submit issues or pull requests on GitHub.
Development
# Clone the repository
# Run tests
# Run examples
# Check formatting
# Run clippy
License
This project is licensed under either of
at your option.
Acknowledgments
This library is inspired by common patterns in Rust async programming and aims to reduce boilerplate when working with shared mutable state across tokio tasks.