Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> `std::cell::Cell` and `std::cell::RefCell` give you (2).

What advantages does (2) provide? Isn't it a potential source of errors?



It is, but sometimes you have to do it for practicality. Usually this comes up when people use `Rc<T>`, as that only supports immutable types (so any mutability you want needs to be in the form of `Cell`/`RefCell`).


Would it be better to combine both types (e.g. a MutRc<T> type), and get rid of Cell/RefCell?


I don't think so, because then you'd get an overconservative iterator invalidation checker. For example:

    struct Foo {
        a: Vec<int>,
        b: Vec<int>,
    }

    let foo = Rc::new(RefCell::new(Foo::new(...)));
    for x in foo.borrow_mut().a.mut_iter() {
        for y in foo.borrow_mut().b.mut_iter() {
            // ^^^ FAILURE: a is already borrowed mutably
        }
    }
The failure happens because the RefCell is checking to make sure there are no two `&mut` references at the same time to `Foo`, to prevent iterator invalidation. But this is silly, because it only needs to prevent access to `a` while you're iterating over it, not both `a` and `b`. Changing the definition of `Foo` to this fixes the problem:

    struct Foo {
        a: RefCell<Vec<int>>,
        b: RefCell<Vec<int>>,
    }


Makes sense. Though Cells would really stand out in the code as a potential for race conditions (unless you get a run time failure?). Thanks for the insight.


There is a special bound--Share--that is required on thread-safe data structures and forbids Cell/RefCell. The thread-safe equivalents of Cell and RefCell are Atomic and Mutex, respectively.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: