I'm learning Rust and trying to create a Admin panel like with egui and multi-threading; One thread which update the Student struct in an Hashmap && another which run egui and display Student information; here the problem, I have:
students: Arc<Hashmap<PathBuf, Mutex<Student>>>
actual_student : Option<Mutex<Student>>
// The student in the popup
// Here when I would like to get the &Student after clicking on a button 'See more'
self.actual_student = Some(self.students.get(path.deref()).unwrap());
// But got the error: lifetime may not live enough assignment requires that `'1` must outlive `'a`
Here the complete code of the implementation:
pub struct Maestro<'a> {
pub students: Arc<HashMap<PathBuf, Mutex<Student>>>,
pub logger: Logger,
pub actual_student: Option<&'a Mutex<Student>>,
// Would like to make like this: pub student: Option<&Student> but cannot get reference to
// Student from mutex's value
}
impl<'a> Maestro<'a> {
pub fn new() -> Self {
let config = load_config();
let watcher = config.watcher;
let students = Arc::new(watcher.init());
let mut students_for_thread = Arc::clone(&students);
std::thread::spawn(move || {
watcher.run(&mut students_for_thread);
});
Maestro {
students,
logger: config.logger,
actual_student: None,
}
}
}
impl<'a> eframe::App for Maestro<'a> {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
egui::CentralPanel::default().show(ctx, |ui| {
for (path, student) in self.students.iter() {
if let Ok(mutex) = student.try_lock() {
ui.horizontal(|ui| {
ui.label(&mutex.name);
match &mutex.bashrc_editable {
true => ui.colored_label(egui::Color32::GREEN, "true"),
false => ui.colored_label(egui::Color32::RED, "false"),
};
if ui.button("See more").clicked() {
if self.students.contains_key(path) {
self.actual_student = Some(self.students.get(path.deref()).unwrap());
// FIXME 10/27/22 ectaclick: lifetime may not live long enough assignment requires that `'1` must outlive `'a`
}
}
});
}
}
});
// Would like to create a 'popup' on the right of the list
if self.actual_student.is_some() {
let student = self.actual_student.unwrap().lock().unwrap();
egui::SidePanel::right("student").show(ctx, |ui| {
ui.label(student.name.as_str());
match student.bashrc_editable {
true => ui.colored_label(Color32::GREEN, "true"),
false => ui.colored_label(Color32::RED, "false"),
}
});
}
std::thread::sleep(Duration::from_millis(100));
}
I tried to many type of actual_student
:
Option<Student>
Box<Student>
Option<&Student>
Tried to clone the value but the actual_student
is not the same of the Student
in the Hashmap
which is the Student
struct updated by the second thread.
But the problem is still the same.