mousetail
mousetail

Reputation: 8010

Shared pointer in rust arrays

I have two arrays:

struct Data {
    all_objects: Vec<Rc<dyn Drawable>>;
    selected_objects: Vec<Rc<dyn Drawable>>;
}

selected_objects is guarenteed to be a subset of all_objects. I want to be able to somehow be able to add or remove mutable references to selected objects.

I can add the objects easily enough to selected_objects:

Rc::get_mut(selected_object).unwrap().select(true);
self.selected_objects.push(selected_object.clone());

However, if I later try:

for obj in self.selected_objects.iter_mut() {
    Rc::get_mut(obj).unwrap().select(false);
}

This gives a runtime error, which matches the documentation for get_mut: "Returns None otherwise, because it is not safe to mutate a shared value."

However, I really want to be able to access and call arbitrary methods on both arrays, so I can efficiently perform operations on the selection, while also being able to still perform operations for all objects.

It seems Rc does not support this, it seems RefMut is missing a Clone() that alows me to put it into multiple arrays, plus not actually supporting dyn types. Box is also missing a Clone(). So my question is, how do you store writable pointers in multiple arrays? Is there another type of smart pointer for this purpose? Do I need to nest them? Is there some other data structure more suitable? Is there a way to give up the writable reference?

Upvotes: 1

Views: 257

Answers (1)

mousetail
mousetail

Reputation: 8010

Ok, it took me a bit of trial and error, but I have a ugly solution:

struct Data {
    all_objects: Vec<Rc<RefCell<dyn Drawable>>>;
    selected_objects: Vec<Rc<RefCell<dyn Drawable>>>;
}

The Rc allows you to store multiple references to an object. RefCell makes these references mutable. Now the only thing I have to do is call .borrow() every time I use a object.

While this seems to work and be reasonably versitle, I'm still open for cleaner solutions.

Upvotes: 1

Related Questions