Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion advanced/state-management.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ persistence_manager.modify_device(|device| {
Device state uses two separate locks with different roles:

- **`device_snapshot` (`std::sync::RwLock<Arc<Device>>`)**: read by `get_device_snapshot()`. Readers never contend with writers — they take a brief `std::sync` read lock to clone the `Arc`, then release immediately. The snapshot is updated inside the `tokio::sync::RwLock` write guard in `modify_device`, so readers always see fully committed state.
- **`device` (`tokio::sync::RwLock<Device>`)**: write-locked inside `modify_device()`. Only store-adapter code that needs `&mut Device` trait access (`get_device_arc()`) takes a read lock here directly.
- **`device` (`tokio::sync::RwLock<Device>`)**: write-locked inside `modify_device()`. As of [whatsapp-rust#1226](https://github.com/oxidezap/whatsapp-rust/pull/1226), the Signal store adapters (`SignalProtocolStoreAdapter`, `SenderKeyAdapter`) no longer take a read lock here on every operation — they hold `Arc<PersistenceManager>` and call `get_device_snapshot()` instead, so a slow backend round-trip on one Signal operation no longer queues every other Signal operation behind this lock. `get_device_arc()` still returns a handle to this lock for any caller that needs `&mut Device` trait access directly; store adapters are no longer among them.
Comment thread
jlucaso1 marked this conversation as resolved.
Outdated

In practice: `get_device_snapshot()` is contention-free for readers, and the tokio write lock is only held during actual mutations (rare).

Expand Down