What is the right smart pointer to have multiple strong references and allow mutability?

☆樱花仙子☆ 提交于 2019-11-29 17:14:23

Rc (and its multithreaded counterpart Arc) only concern themselves with ownership. Instead of a single owner, there is now joint ownership, tracked at runtime.

Mutability is a different concept, although closely related to ownership: if you own a value, then you have the ability to mutate it. This is why Rc::get_mut only works when there is a single strong reference - it's the same as saying there is a single owner.

If you need the ability to divide mutability in a way that doesn't match the structure of the program, you can use tools like Cell or RefCell for single-threaded programs:

use std::cell::RefCell;

fn create() -> Rc<RefCell<Foo>> {
    let rc = Rc::new(RefCell::new(Foo { val: 5 }));
    let weak_rc = Rc::downgrade(&rc);
    need_callback(move |x| {
        if let Some(rc) = weak_rc.upgrade() {
            rc.borrow_mut().set_val(x);
        }
    });
    rc
}

Or Mutex, RwLock, or an atomic type in multithreaded contexts:

use std::sync::Mutex;

fn create() -> Rc<Mutex<Foo>> {
    let rc = Rc::new(Mutex::new(Foo { val: 5 }));
    let weak_rc = Rc::downgrade(&rc);
    need_callback(move |x| {
        if let Some(rc) = weak_rc.upgrade() {
            if let Ok(mut foo) = rc.try_lock() {
                foo.set_val(x);
            }
        }
    });
    rc
}

These tools all defer the check that there is only a single mutable reference to runtime, instead of compile time.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!