Rc<RefCell<T>> combines shared ownership with checked interior mutation for single-threaded state.

Program

Play the program to choose an event and append it through a cloned owner.

rc_refcell_log.rs
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let event = ;
    let log = Rc::new(RefCell::new(Vec::new()));
    let worker = Rc::clone(&log);
    record(&log, "start");
    record(&worker, event);
    let joined = log.borrow().join(",");
    println!("{} owners={}", joined, Rc::strong_count(&log));
}

fn record(log: &Rc<RefCell<Vec<&'static str>>>, event: &'static str) {
    log.borrow_mut().push(event);
}
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let event = ;
    let log = Rc::new(RefCell::new(Vec::new()));
    let worker = Rc::clone(&log);
    record(&log, "start");
    record(&worker, event);
    let joined = log.borrow().join(",");
    println!("{} owners={}", joined, Rc::strong_count(&log));
}

fn record(log: &Rc<RefCell<Vec<&'static str>>>, event: &'static str) {
    log.borrow_mut().push(event);
}
use std::cell::RefCell;
use std::rc::Rc;

fn main() {
    let event = ;
    let log = Rc::new(RefCell::new(Vec::new()));
    let worker = Rc::clone(&log);
    record(&log, "start");
    record(&worker, event);
    let joined = log.borrow().join(",");
    println!("{} owners={}", joined, Rc::strong_count(&log));
}

fn record(log: &Rc<RefCell<Vec<&'static str>>>, event: &'static str) {
    log.borrow_mut().push(event);
}
Rc `Rc` gives multiple owners of the same single-threaded value.
RefCell `RefCell` checks borrow rules at runtime so the log can be mutated through shared owners.
shared log Both `log` and `worker` point to the same vector, so both records appear together.