Is there a way to create an Arc if Weak::upgrade return None? Something like Weak::upgrade_or_create?
For example
fn do_something(weak: &Weak<u32>) {
let arc: Arc<u32> = weak.upgrade_or_insert(Arc::new(42));
// do something ...
}
Notice that I cannot just create an arc and downgrade it and assign to weak:
fn do_something(weak: &Weak<u32>) {
let arc: Arc<u32> = match weak.upgrade() {
None => {
let arc = Arc::new(42);
*weak = Arc::downgrade(&arc); // will not work, since weak is not mutable
arc
}
Some(arc) => { arc }
};
// do something ...
}
because the weak is not mutable.
P.S. Please correct me if I'm wrong, I think a function like upgrade_or_insert work on an immutable weak is totally safe, since the newly created Arc do not get overlap memory writing problem.
It's not clear what exact semantics you are expecting. You don't need to go back and forth between Arc and Weak, nor do you need a mutable Weak for this. Just write
let arc = weak.upgrade().unwrap_or_else(|| Arc::new(42));
If you only have an immutable reference to Weak, then it's not possible for you to change it to point to your new Arc. You would need a mutable reference to do that, and in that case the match you posted will work.
If you’re proposing adding such a method to the standard library, you’ll want to open a thread on IRLO instead of here. You’ll need a design that avoids the data race @alice mentioned, though.
Mutable reference is not enough as there can be multiple Weaks pointing to same allocation. To ensure the replaced value is stored some kind of locking mechanism is needed.
It seems like you are making the mistake discussed here at 20:46. The ptr field in an Arc (or Weak) is not atomic, and the standard library is not going to change it to be an atomic.
I assumed that only the weak it was called on would be updated, and not other clones of the same weak. It's possible that I misunderstood.