3

I am looking for a smart pointer similar to Arc/Rc except that it does not allow shared ownership.

I want to have as many rc::Weak references as I need, but I only want one strong reference, a.k.a owner. And I want to enforce that with the type system.

Arc/Rc can be cloned, and they can be owned at several places.

Rolling up my own smart pointer would be an option, but I believe such data structure should already exist, even if outside the standard library.

I am looking for a data structure providing this kind of interface:

impl MySmartPointer<T> {
    fn new(object: T) -> Self;
    fn weak_ref(&self) -> WeakRef<T>;
    fn get_mut(&mut self) -> &mut T;
}

impl WeakRef<T> {
    /// If the strong pointer `MySmartPointer` has been dropped,
    /// return `None`. Else return Some(&T);
    fn get(&self) -> Option<&T>;
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Olivier
  • 773
  • 9
  • 14
  • 1
    Do you mean something like [`RwLock`](https://doc.rust-lang.org/std/sync/struct.RwLock.html)? – Jorge Israel Peña Jun 07 '18 at 23:54
  • I do not think that RwLock will do the trick. Even though RwLock can be owned in one place, I do not think I can throw around weak references to the value encapsulated by RwLock. What if the original RwLock gets deleted? – Olivier Jun 08 '18 at 03:38
  • 1
    Just for information, what is a usecase for this? – Boiethios Jun 08 '18 at 08:55
  • @JorgeIsraelPeña RW locks can chose to let more reader enter or more writers. They can have different levels of writers that more or less force readers to wait... The last (or last and only) master_strong owner of a resource could decide to invalidate the weak owners, only letting those who had already upgraded to strong_from_weak, who wouldn't be able to create more owners. It's a "we are closing, only those customers in the line can check out" decision. – curiousguy Jun 10 '18 at 06:03

1 Answers1

8

Let's assume it exists with types Strong<T> and Weak<T>. How do you use Weak<T>? You need some kind of fallible "upgrade" step, so what does Weak<T> upgrade to? It can't be to a plain reference (as you've stated), because Strong<T> needs to know whether or not any "upgraded" Weak<T>s exist. If it didn't, it could deallocate its storage whilst the value is still being accessed.

So Weak<T> must upgrade to some kind of SemiWeak<T> which keeps the underlying allocation alive... which is exactly what shared ownership is.

What if you somehow guaranteed that Strong<T> couldn't be deallocated before all Weak<T>s go away? Congratulations, you've just re-invented T and &T: you could literally just use those instead.

Alright, so what if you made it so that Weak<T> upgrades into a SemiWeak<'a, T> that is tied to the lifetime of the Weak<T> so that it can't outlive it, and can only be a temporary? All you're really doing in that case is hiding the fact that you've got shared ownership. Under the hood, SemiWeak would still need to guarantee the underlying Strong can't go away. You could trivially build such a type from Rc<T> in perhaps ten minutes. This would effectively give you a type that is exactly like Rc<T>, with the same performance and memory cost, but less useful.

In addition, that get_mut method can't exist. There's no way to prevent SemiWeak<T>s from existing. Unless you use borrowing but, again, that's just using T and &T.

So, no, I don't think this exists, nor do I believe it can in the form you've described.


As a final aside, just having Weak<T> at all is a form of shared ownership, because those Weak<T>s need to point to something. In the case of Rc<T>, the weak counter is stored right alongside the strong counter, so whilst the value can be destroyed, the allocation itself sticks around. You could split the two, but now you're paying for two allocations and double indirection (probably leading to more cache misses).

DK.
  • 55,277
  • 5
  • 189
  • 162
  • IOW, a "weak reference" is a strong reference to meta info. – curiousguy Jun 08 '18 at 22:57
  • You could still have a bunch of strong references and weaker strong references that keep the object alive but that don't keep weak references upgradable. The store is closing, some customers will still be allowed to buy what they have in their cart, other will have to leave... You can prevent some customers from upgrading to close earlier. – curiousguy Jun 10 '18 at 05:57