wasm_safe_mutex

A WebAssembly-safe mutex that papers over platform-specific locking constraints.
The Core Problem
WebAssembly's main thread cannot use blocking locks - attempting to do so will panic with "cannot block on the main thread". This is a fundamental limitation of the browser environment where blocking the main thread would freeze the entire UI.
However, blocking locks ARE allowed in:
- WebAssembly worker threads (where
Atomics.waitis available) - Native platforms (both main and worker threads)
- Most non-WASM contexts (traditional OS threads have no such restrictions)
The Solution
This crate papers over all these platform differences by automatically adapting its locking strategy based on the runtime environment:
- Native (any thread): Uses efficient thread parking (
thread::park) - WASM worker threads: Uses
Atomics.waitwhen available - WASM main thread: Falls back to spinning (non-blocking busy-wait)
This means you can write code once and have it work correctly across all platforms, without worrying about whether you're on the main thread, a worker thread, native or WASM.
Features
- Transparent adaptation: Automatically detects and uses the best available locking mechanism
- Main thread safe: Won't panic on WASM main thread (uses spinning instead)
- Worker thread optimized: Uses proper blocking when available for efficiency
- Native performance: Full thread parking on native platforms
- Async support: Non-blocking async methods that work everywhere
- Multiple strategies: Try-lock, spin-lock, blocking lock, and async lock
Installation
Add this to your Cargo.toml:
[]
= "0.1.0"
Examples
Basic Usage
use Mutex;
let mutex = new;
let mut guard = mutex.lock_sync;
*guard = 100;
drop;
// Value has been updated
let guard = mutex.lock_sync;
assert_eq!;
Try Lock
use ;
let mutex = new;
// First lock succeeds
let guard = mutex.try_lock.unwrap;
assert_eq!;
// Second lock fails while first is held
let result = mutex.try_lock;
assert!;
Async Usage
use Mutex;
let mutex = new;
// Async lock doesn't block the executor
let mut guard = mutex.lock_async.await;
guard.push;
drop;
// Using the convenience method
let sum = mutex.with_async.await;
assert_eq!;
Thread-Safe Sharing
use Mutex;
use Arc;
use thread;
let mutex = new;
let handles: =
.map
.collect;
for handle in handles
assert_eq!;
API Overview
The Mutex<T> type provides multiple locking strategies:
Locking Methods
try_lock(): Non-blocking attempt to acquire the locklock_spin(): Spin-wait until the lock is acquiredlock_block(): Blocks on native/WASM workers, spins on WASM main threadlock_sync(): Automatically chooses the right strategy for your platform (recommended)lock_async(): Always non-blocking, works everywhere including WASM main thread
Convenience Methods
with_sync(): Execute a read-only closure with the lockwith_mut_sync(): Execute a mutable closure with the lockwith_async(): Execute a read-only closure with the lock asynchronouslywith_mut_async(): Execute a mutable closure with the lock asynchronously
Platform Behavior
The mutex transparently handles platform differences:
- Native (main or worker thread): Full blocking with thread parking
- WASM worker threads: Blocks using
Atomics.wait - WASM main thread: Spins to avoid "cannot block on main thread" panic
This automatic adaptation means your code works everywhere without modification.