use eframe::egui;
use facet::Facet;
use facet_egui::FacetProbe;
use std::sync::{Arc, Mutex, RwLock, Weak};
#[derive(Debug, Facet, Default)]
struct SharedState {
message: String,
count: u32,
}
#[derive(Debug, Facet)]
struct Model {
weak_outer: Weak<Mutex<Arc<RwLock<Mutex<SharedState>>>>>,
weak_inner: Weak<RwLock<RwLock<SharedState>>>,
}
struct App {
strong_inner: Arc<RwLock<RwLock<SharedState>>>,
strong_outer: Arc<Mutex<Arc<RwLock<Mutex<SharedState>>>>>,
model: Model,
extra: ExtraWeaks,
}
impl App {
fn new() -> Self {
let inner = RwLock::new(SharedState {
message: "Nested Arc/Mutex/RwLock example (inner)".to_owned(),
count: 0,
});
let strong_inner = Arc::new(RwLock::new(inner));
let outer_inner = Mutex::new(SharedState {
message: "Nested Arc/Mutex/RwLock example (outer)".to_owned(),
count: 0,
});
let outer_arc = Arc::new(RwLock::new(outer_inner));
let strong_outer: Arc<Mutex<Arc<RwLock<Mutex<SharedState>>>>> =
Arc::new(Mutex::new(outer_arc));
let model = Model {
weak_outer: Arc::downgrade(&strong_outer),
weak_inner: Arc::downgrade(&strong_inner),
};
let extra = ExtraWeaks {
weak_outer: Arc::downgrade(&strong_outer),
weak_inner: Arc::downgrade(&strong_inner),
weak_behind_rwlock: RwLock::new(Arc::downgrade(&strong_inner)),
};
Self {
strong_inner,
strong_outer,
model,
extra,
}
}
}
#[derive(Debug, Facet)]
struct ExtraWeaks {
weak_outer: Weak<Mutex<Arc<RwLock<Mutex<SharedState>>>>>,
weak_inner: Weak<RwLock<RwLock<SharedState>>>,
weak_behind_rwlock: RwLock<Weak<RwLock<RwLock<SharedState>>>>,
}
impl eframe::App for App {
fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ui, |ui| {
ui.heading("Nested Arc/Weak + Mutex + RwLock example");
ui.label("Probe the `Model` below; it contains Weak pointers to both levels.");
ui.separator();
FacetProbe::new(&mut self.model)
.readonly(false)
.expand_all(true)
.show(ui);
ui.separator();
ui.label("Extra Weaks (separate field):");
FacetProbe::new(&mut self.extra)
.readonly(true)
.expand_all(true)
.show(ui);
ui.separator();
if let Ok(outer_read) = self.strong_inner.read()
&& let Ok(inner_read) = outer_read.read()
{
ui.label(format!(
"Inner state => message: {}, count: {}",
inner_read.message, inner_read.count
));
}
if let Ok(outer_guard) = self.strong_outer.lock() {
let arc_rw = outer_guard.clone();
if let Ok(rw) = arc_rw.read()
&& let Ok(ms) = rw.lock()
{
ui.label(format!(
"Outer state => message: {}, count: {}",
ms.message, ms.count
));
}
}
if ui.button("Increment via strong inner").clicked()
&& let Ok(outer_write) = self.strong_inner.write()
&& let Ok(mut inner_write) = outer_write.write()
{
inner_write.count += 1;
}
if ui.button("Increment via strong outer").clicked()
&& let Ok(outer_guard) = self.strong_outer.lock()
{
let arc_rw = outer_guard.clone();
if let Ok(rw_write) = arc_rw.write()
&& let Ok(mut ms) = rw_write.lock()
{
ms.count += 1;
}
}
if ui.button("Replace inner (drop strong)").clicked() {
let new_inner = RwLock::new(SharedState::default());
self.strong_inner = Arc::new(RwLock::new(new_inner));
}
if ui.button("Replace outer (drop outer)").clicked() {
let new_outer_inner = Mutex::new(SharedState::default());
let new_arc = Arc::new(RwLock::new(new_outer_inner));
self.strong_outer = Arc::new(Mutex::new(new_arc));
}
});
}
}
fn main() -> eframe::Result<()> {
let options = eframe::NativeOptions::default();
eframe::run_native(
"Nested Arcs example",
options,
Box::new(|_cc| Ok(Box::new(App::new()))),
)
}