I’m porting some code from Go. This code uses multiple pointers to one atomic pointer, that can be swapped from any thread at any time. In Rust terms it would be something like:
struct Logger {
shared_atomic_handler * mut AtomicPtr<Handler>
}
As Go has GC, there’s no problem with ownership on swap of AtomicPtr
, as both new and old Handler
instance will be alive as long as needed and GCed when not referenced anymore by anyone. In Rust one could do atomic swap on the AtomicPtr
, but there’s no way to know when (if ever) the old Handler
instance is OK to free.
However, I see no way to port it to Rust, that wouldn’t require me to use spinlock/mutex (which is undesirable, especially in hot path of the logging library that I’m porting).
It seems to me that if Arc had an atomic swap, the problem would be solved with:
struct Logger {
shared_atomic_handler Arc<Arc<Handler>>
}
impl Logger {
fn swap(&self, new_handler : Arc<Handler>) {
Arc::swap(& *self.shared_atomic_handler, &new_handler)
}
}
The Arc::swap
would convert:
A ----> N
A -\
A ---> A ----> O
A --/ /
A-
where A
is Arc
, O
- old (previous) handler (that has a additional reference), and N
- new handler into:
A -\ /- N
A -\ X
A ---> A -/ \- > O
A --/ /
A-
As you can see total number of references for N
and O
does not change, so could this be an atomic operation (swap on Arc’s inner pointer maybe)?
If not, does anyone see any good solution to my original porting problem?