shared-container 0.1.1

A unified abstraction for shared data access in both multi-threaded and single-threaded environments
Documentation

Shared Container

A unified abstraction for shared data access in both multi-threaded and single-threaded environments.

Crates.io Documentation License: MIT

Overview

shared-container provides a unified abstraction over different container types used for shared data access with interior mutability in different contexts. It abstracts over the differences between:

  • Thread-safe Arc<RwLock<T>> used in multi-threaded environments
  • Rc<RefCell<T>> used in single-threaded environments like WebAssembly

This allows code using these containers to be written once but work efficiently in both contexts.

Features

  • Platform-aware implementation: Automatically uses the most efficient implementation based on the target platform
  • Unified API: Same API for both multi-threaded and single-threaded environments
  • Read/Write access: Provides both read-only and read-write access to the contained data
  • Weak references: Supports weak references to prevent reference cycles
  • Clone support: Containers can be cloned to create multiple references to the same data
  • Transparent access: Uses Rust's deref mechanism for ergonomic access to the contained data

Usage

Add this to your Cargo.toml:

[dependencies]
shared-container = "0.1.1"

Basic Example

use shared_container::SharedContainer;

// Create a new container with a value
let container = SharedContainer::new(42);

// Read access
if let Some(guard) = container.read() {
    println!("Value: {}", *guard);
}

// Write access
if let Some(mut guard) = container.write() {
    *guard = 100;
}

// Clone the container (both point to the same data)
let container2 = container.clone();

// Changes through one container are visible through the other
if let Some(guard) = container2.read() {
    assert_eq!(*guard, 100);
}

// Create a weak reference
let weak = container.downgrade();

// Upgrade weak reference to strong reference
if let Some(container3) = weak.upgrade() {
    // Use container3...
}

Working with Custom Types

use shared_container::SharedContainer;
use std::fmt::Debug;

#[derive(Debug, Clone)]
struct User {
    id: u64,
    name: String,
}

let user = User {
    id: 1,
    name: "Alice".to_string(),
};

let container = SharedContainer::new(user);

// Get a clone of the contained value
if let Some(user_clone) = container.get_cloned() {
    println!("User: {:?}", user_clone);
}

// Modify the user
if let Some(mut guard) = container.write() {
    guard.name = "Bob".to_string();
}

Platform-specific Behavior

  • On native platforms, SharedContainer<T> uses Arc<RwLock<T>> internally
  • On WebAssembly (wasm32 target), it uses Rc<RefCell<T>> internally
  • The API remains the same, but the behavior differs slightly:
    • On native platforms, read/write operations can fail if the lock is poisoned
    • On WebAssembly, read/write operations can fail if there's already a borrow

Testing WebAssembly Compatibility

This library includes a feature flag to help test WebAssembly compatibility even on native platforms:

[dependencies]
shared-container = { version = "0.1.1", features = ["force-wasm-impl"] }

When the force-wasm-impl feature is enabled, the library will use the WebAssembly implementation (Rc<RefCell<T>>) even when compiling for native platforms. This allows you to test WebAssembly-specific behavior without actually compiling to WebAssembly.

To run the WebAssembly-specific tests:

cargo test --features force-wasm-impl

License

This project is licensed under the MIT License - see the LICENSE file for details.