3 ms·
Mutating a container through a shared reference means the container either has to be single-threaded (not marked as Sync/Send), or be thread-safe. The single-t
by whytevuhuni 2y ago
Mutating a container through a shared reference means the container either has to be single-threaded (not marked as Sync/Send), or be thread-safe.
The single-threaded ones are easy to make, but Rust will prevent you from sending them to another thread, which is probably something you want.
For thread-safe things, look into the crossbeam crate, it has really good collections.
One I worked with was the dashmap, which has a .retain() method [1] that works over a shared map reference, but runs a closure which gets mutable access to each key and value, and decides whether to keep the pair or not.
Its .get() [2] uses equality (so you can use a different object), but returns a reference to the original key-value pair. The .get_mut() will return it as mutable, but inside a guard that keeps the item locked until it goes out of scope.
[1] https://docs.rs/dashmap/latest/dashmap/struct.DashMap.html#method.retain https://docs.rs/dashmap/latest/dashmap/struct.DashMap.html#m...
[2] https://docs.rs/dashmap/latest/dashmap/struct.DashMap.html#method.get https://docs.rs/dashmap/latest/dashmap/struct.DashMap.html#m...
- o11c 2y ago`.retain()` unfortunately isn't what I'm talking about, since it's at least O(n) per call. It might be better if you can arrange to call it just once after a batch of operations, but that isn't always the case. "Delete as you go" usually† adds no space/time complexity to the operations you're already doing (though it does affect the constant factor). It does mean you're giving up on predictable destructor calls, but generally the "heavy" destructor was called by whoever made it expire (e.g. the death of the last remaining shared owner if that's what expiry is based on). † If many expirations happen at once, this can easily drop to merely amortized time. It's also possible for a container to offer, say, O(1) iteration via dedicated pointers but have a delete operation that's more complicated.