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.
This commit is contained in:
Emil Ernerfeldt 2020-08-28 15:45:26 +02:00
parent 98bced7e62
commit 373b1c2911

View file

@ -1,6 +1,9 @@
use std::sync::Arc; use std::sync::Arc;
use {ahash::AHashMap, parking_lot::Mutex}; use {
ahash::AHashMap,
parking_lot::{Mutex, MutexGuard},
};
use crate::{paint::*, *}; use crate::{paint::*, *};
@ -63,16 +66,16 @@ impl Context {
Rect::from_min_size(pos2(0.0, 0.0), self.input.screen_size) Rect::from_min_size(pos2(0.0, 0.0), self.input.screen_size)
} }
pub fn memory(&self) -> parking_lot::MutexGuard<'_, Memory> { pub fn memory(&self) -> MutexGuard<'_, Memory> {
self.memory.try_lock().expect("memory already locked") lock(&self.memory, "memory")
} }
pub fn graphics(&self) -> parking_lot::MutexGuard<'_, GraphicLayers> { pub fn graphics(&self) -> MutexGuard<'_, GraphicLayers> {
self.graphics.try_lock().expect("graphics already locked") lock(&self.graphics, "graphics")
} }
pub fn output(&self) -> parking_lot::MutexGuard<'_, Output> { pub fn output(&self) -> MutexGuard<'_, Output> {
self.output.try_lock().expect("output already locked") lock(&self.output, "output")
} }
/// Call this if there is need to repaint the UI, i.e. if you are showing an animation. /// 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 // TODO: return MutexGuard
pub fn style(&self) -> Style { 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) { 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 { pub fn pixels_per_point(&self) -> f32 {
@ -578,3 +581,17 @@ impl PaintStats {
ui.add(label!("Triangles: {}", self.num_triangles)); ui.add(label!("Triangles: {}", self.num_triangles));
} }
} }
#[cfg(debug_assertions)]
fn lock<'m, T>(mutex: &'m Mutex<T>, 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<T>, _what: &'static str) -> MutexGuard<'m, T> {
mutex.lock()
}