Eugene Sh.
Eugene Sh.

Reputation: 18331

Constructor for a structure with weak reference to its owner

Trying to implement a data structure where many "things" can be owned by an "owner", while each "thing" should know who its owner is. As far as I understand it can be achieved by having a Weak reference to the owner in each "thing". The question I cannot figure out how to implement the constructor (new) function for these structures. Here is a simplified structure of what I am trying to do:

use std::rc::{Rc, Weak};

struct Owner {
    thing1: Thing,
    thing2: Thing,
}

impl Owner {
    fn new() -> Self {
        Self {
            thing1: Thing::new(???),   // 1
            thing2: Thing::new(???),   // 1
        }
    }
}

struct Thing {
    owner: Weak<Owner>,
    value: u32,
}

impl Thing {
    fn new(owner: ???) -> Self {      // 2
        Self {
            owner: Weak::clone(???),  // 2
            value: 0,
        }
    }
}

So here I can't figure out two things:

  1. When constructing Owner - how to pass itself as a parameter to the constructor of "things" ?
  2. When constructing the Thing - how exactly create the reference to the owner?

Perhaps my approach is completely wrong, in this case please suggest the right one.

Update:
A more concrete example of a use-case for such a structure: Consider an electronic circuit simulation, where each "thing" is a pin of an electronic component, which is the "owner". So each time the value of a pin is externally changed, it should trigger the owner component, which in turn will change the other connector values.

Upvotes: 2

Views: 784

Answers (1)

Coder-256
Coder-256

Reputation: 5618

First, as others have mentioned, this is likely a bad idea that will not only cause poor performance but will be very difficult to code with. With that warning, on to the answer.

This is a bit tricky because today in stable Rust, you would need to initialize the owner in order to get a reference to it (so you would probably need each field to be Option<Thing>; not ideal).

However, as luck would have it, there is an new unstable method Rc::new_cyclic which I think does exactly what you want:

Playground

#![feature(arc_new_cyclic)]

use std::rc::{Rc, Weak};

struct Owner {
    thing1: Thing,
    thing2: Thing,
}

impl Owner {
    fn new() -> Rc<Self> {
        Rc::new_cyclic(|weak| {
            Self {
                thing1: Thing::new(weak.clone()),
                thing2: Thing::new(weak.clone()),
            }
        })
    }
}

struct Thing {
    owner: Weak<Owner>,
    value: u32,
}

impl Thing {
    fn new(owner: Weak<Owner>) -> Self {
        Self {
            owner,
            value: 0,
        }
    }
}

Upvotes: 2

Related Questions