From 373b1c2911157c17d70a89e5fa3cca46d0178a69 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 28 Aug 2020 15:45:26 +0200 Subject: [PATCH] Allow multithreaded use of egui ...but currently only in release build, because in debug builds I want to be able to debug dead-locks from locking the same resource from the same thread. --- egui/src/context.rs | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/egui/src/context.rs b/egui/src/context.rs index 30c288cd..1f7b1477 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -1,6 +1,9 @@ use std::sync::Arc; -use {ahash::AHashMap, parking_lot::Mutex}; +use { + ahash::AHashMap, + parking_lot::{Mutex, MutexGuard}, +}; use crate::{paint::*, *}; @@ -63,16 +66,16 @@ impl Context { Rect::from_min_size(pos2(0.0, 0.0), self.input.screen_size) } - pub fn memory(&self) -> parking_lot::MutexGuard<'_, Memory> { - self.memory.try_lock().expect("memory already locked") + pub fn memory(&self) -> MutexGuard<'_, Memory> { + lock(&self.memory, "memory") } - pub fn graphics(&self) -> parking_lot::MutexGuard<'_, GraphicLayers> { - self.graphics.try_lock().expect("graphics already locked") + pub fn graphics(&self) -> MutexGuard<'_, GraphicLayers> { + lock(&self.graphics, "graphics") } - pub fn output(&self) -> parking_lot::MutexGuard<'_, Output> { - self.output.try_lock().expect("output already locked") + pub fn output(&self) -> MutexGuard<'_, Output> { + lock(&self.output, "output") } /// Call this if there is need to repaint the UI, i.e. if you are showing an animation. @@ -109,11 +112,11 @@ impl Context { // TODO: return MutexGuard pub fn style(&self) -> Style { - self.style.try_lock().expect("style already locked").clone() + lock(&self.style, "style").clone() } pub fn set_style(&self, style: Style) { - *self.style.try_lock().expect("style already locked") = style; + *lock(&self.style, "style") = style; } pub fn pixels_per_point(&self) -> f32 { @@ -578,3 +581,17 @@ impl PaintStats { ui.add(label!("Triangles: {}", self.num_triangles)); } } + +#[cfg(debug_assertions)] +fn lock<'m, T>(mutex: &'m Mutex, what: &'static str) -> MutexGuard<'m, T> { + // TODO: detect if we are trying to lock the same mutex *from the same thread*. + // at the moment we just panic on any double-locking of a mutex (so no multithreaded support in debug builds) + mutex + .try_lock() + .unwrap_or_else(|| panic!("The Mutex for {} is already locked. Probably a bug", what)) +} + +#[cfg(not(debug_assertions))] +fn lock<'m, T>(mutex: &'m Mutex, _what: &'static str) -> MutexGuard<'m, T> { + mutex.lock() +}