Prism3 Concurrent
A comprehensive Rust concurrent utilities library providing thread-safe lock wrappers and synchronization primitives for the Prism3 ecosystem.
Overview
Prism3 Concurrent provides easy-to-use wrappers around both synchronous and asynchronous locks, offering a unified interface for concurrent programming in Rust. All lock types have Arc built-in internally, so you can clone and share them across threads or tasks directly without additional wrapping. The library provides convenient helper methods for common locking patterns with a closure-based API that ensures proper lock management.
Features
🔒 Synchronous Locks
- ArcMutex: Thread-safe mutual exclusion lock wrapper with
Arcintegration - ArcRwLock: Thread-safe read-write lock wrapper supporting multiple concurrent readers
- Convenient API:
with_lockandtry_with_lockmethods for cleaner lock handling - Automatic RAII: Ensures proper lock release through scope-based management
🚀 Asynchronous Locks
- ArcAsyncMutex: Async-aware mutual exclusion lock for use with Tokio runtime
- ArcAsyncRwLock: Async-aware read-write lock supporting concurrent async reads
- Non-blocking: Designed for async contexts without blocking threads
- Tokio Integration: Built on top of Tokio's synchronization primitives
🎯 Key Benefits
- Clone Support: All lock wrappers implement
Clonefor easy sharing across threads - Type Safety: Leverages Rust's type system for compile-time guarantees
- Ergonomic API: Closure-based lock access eliminates common pitfalls
- Production Ready: Battle-tested locking patterns with comprehensive test coverage
Installation
Add this to your Cargo.toml:
[]
= "0.1.0"
Quick Start
Synchronous Mutex
use ArcMutex;
use thread;
Synchronous Read-Write Lock
use ArcRwLock;
Asynchronous Mutex
use ArcAsyncMutex;
async
Asynchronous Read-Write Lock
use ArcAsyncRwLock;
async
Try Lock (Non-blocking)
use ArcMutex;
API Reference
ArcMutex
A synchronous mutual exclusion lock wrapper with Arc integration.
Methods:
new(data: T) -> Self- Create a new mutexwith_lock<F, R>(&self, f: F) -> R- Acquire lock and execute closuretry_with_lock<F, R>(&self, f: F) -> Option<R>- Try to acquire lock without blockingclone(&self) -> Self- Clone the Arc reference
ArcRwLock
A synchronous read-write lock wrapper supporting multiple concurrent readers.
Methods:
new(data: T) -> Self- Create a new read-write lockwith_read_lock<F, R>(&self, f: F) -> R- Acquire read lockwith_write_lock<F, R>(&self, f: F) -> R- Acquire write lockclone(&self) -> Self- Clone the Arc reference
ArcAsyncMutex
An asynchronous mutual exclusion lock for Tokio runtime.
Methods:
new(data: T) -> Self- Create a new async mutexasync with_lock<F, R>(&self, f: F) -> R- Asynchronously acquire locktry_with_lock<F, R>(&self, f: F) -> Option<R>- Try to acquire lock (non-blocking)clone(&self) -> Self- Clone the Arc reference
ArcAsyncRwLock
An asynchronous read-write lock for Tokio runtime.
Methods:
new(data: T) -> Self- Create a new async read-write lockasync with_read_lock<F, R>(&self, f: F) -> R- Asynchronously acquire read lockasync with_write_lock<F, R>(&self, f: F) -> R- Asynchronously acquire write lockclone(&self) -> Self- Clone the Arc reference
Design Patterns
Closure-Based Lock Access
All locks use closure-based access patterns for several benefits:
- Automatic Release: Lock is automatically released when closure completes
- Exception Safety: Lock is released even if closure panics
- Reduced Boilerplate: No need to manually manage lock guards
- Clear Scope: Lock scope is explicitly defined by closure boundaries
Arc Integration
Important: All ArcMutex, ArcRwLock, ArcAsyncMutex, and ArcAsyncRwLock types already have Arc integrated internally. You don't need to wrap them with Arc again.
// ✅ Correct - use directly
let lock = new;
let lock_clone = lock.clone; // Clones the internal Arc
// ❌ Wrong - unnecessary double wrapping
let lock = new; // Don't do this!
This design provides several benefits:
- Easy Cloning: Share locks across threads/tasks with simple
.clone() - No Extra Wrapping: Use directly without additional
Arcallocation - Reference Counting: Automatic cleanup when last reference is dropped
- Type Safety: Compiler ensures proper usage patterns
Use Cases
1. Shared Counter
Perfect for maintaining shared state across multiple threads:
let counter = new;
// Share counter across threads
let counter_clone = counter.clone;
spawn;
2. Configuration Cache
Read-write locks are ideal for configuration that's read frequently but written rarely:
let config = new;
// Many readers
config.with_read_lock;
// Occasional writer
config.with_write_lock;
3. Async Task Coordination
Coordinate state between async tasks without blocking threads:
let state = new;
let state_clone = state.clone;
spawn;
Dependencies
- tokio: Async runtime and synchronization primitives (features:
sync) - std: Standard library synchronization primitives (
Mutex,RwLock,Arc)
Testing & Code Coverage
This project maintains comprehensive test coverage with detailed validation of all functionality.
Coverage Metrics
Current test coverage statistics:
| Module | Region Coverage | Line Coverage | Function Coverage |
|---|---|---|---|
| lock.rs | 100.00% | 100.00% | 100.00% |
| Total | 100.00% | 100.00% | 100.00% |
Test Scenarios
The test suite covers:
- ✅ Basic lock operations - Creating and using locks
- ✅ Clone semantics - Sharing locks across threads/tasks
- ✅ Concurrent access patterns - Multiple threads/tasks accessing shared data
- ✅ Lock contention scenarios - Testing under high contention
- ✅ Try lock operations - Non-blocking lock attempts
- ✅ Poison handling - Synchronous lock poisoning scenarios
Running Tests
# Run all tests
# Run with coverage report
# Generate text format report
# Generate detailed HTML report
Coverage Tool Information
The coverage statistics are generated using cargo-llvm-cov. For more details on how to run coverage tests and interpret results, see:
- COVERAGE.md - English coverage documentation
- COVERAGE.zh_CN.md - Chinese coverage documentation
- Project coverage reports in
target/llvm-cov/html/
Performance Considerations
Synchronous vs Asynchronous
- Synchronous locks (
ArcMutex,ArcRwLock): Use for CPU-bound operations or when already in a thread-based context - Asynchronous locks (
ArcAsyncMutex,ArcAsyncRwLock): Use within async contexts to avoid blocking the executor
Read-Write Locks
Read-write locks (ArcRwLock, ArcAsyncRwLock) are beneficial when:
- Read operations significantly outnumber writes
- Read operations are relatively expensive
- Multiple readers can genuinely execute in parallel
For simple, fast operations or equal read/write patterns, regular mutexes may be simpler and faster.
License
Copyright (c) 2025 3-Prism Co. Ltd. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
See LICENSE for the full license text.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
When contributing tests, ensure:
- All lock types are tested (synchronous and asynchronous)
- Concurrent scenarios are validated
- Edge cases are covered (try_lock failures, poisoning, etc.)
Author
Hu Haixing - 3-Prism Co. Ltd.
For more information about the Prism3 ecosystem, visit our GitHub homepage.