1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-02 06:40:06 -04:00

Replace parking_lot with atomic_refcell

You can still opt-in to use parking_lot if you plan to use the same
egui::Context from multiple threads.
This commit is contained in:
Emil Ernerfeldt
2020-12-26 20:36:25 +01:00
parent 58fcf0f2a1
commit 6f5fd1b9c0
6 changed files with 104 additions and 21 deletions

View File

@@ -20,7 +20,8 @@ include = [
[dependencies]
ahash = { version = "0.6", features = ["std"], default-features = false }
parking_lot = "0.11" # Using parking_lot over std::sync::Mutex gives 50% speedups in some real-world scenarios
atomic_refcell = { version = "0.1", optional = true } # Used instead of parking_lot when you are always using Egui in a single thread. About as fast as parking_lot.
parking_lot = { version = "0.11", optional = true } # Using parking_lot over std::sync::Mutex gives 50% speedups in some real-world scenarios
rusttype = "0.9"
serde = { version = "1", features = ["derive"], optional = true }
serde_json = { version = "1", optional = true }
@@ -28,6 +29,10 @@ serde_json = { version = "1", optional = true }
[dev-dependencies]
criterion = { version = "0.3", default-features = false }
[features]
default = ["atomic_refcell"] # Using the same egui::Context from multiple threads will result in a panic.
multi_threaded = ["parking_lot"] # Only needed if you plan to use the same egui::Context from multiple threads.
[[bench]]
name = "benchmark"
harness = false

View File

@@ -2,13 +2,12 @@ use std::sync::Arc;
use {
ahash::AHashMap,
parking_lot::RwLock,
rusttype::{point, Scale},
};
use crate::{
math::{vec2, Vec2},
mutex::Mutex,
mutex::{Mutex, RwLock},
paint::{Galley, Row},
};

View File

@@ -1,12 +1,15 @@
//! Helper module for a Mutex that
//! detects double-locking on the same thread in debug mode.
//! Helper module that wraps some Mutex types with different implementations.
// TODO: feature-flag for `parking_lot` vs `std::sync::Mutex`.
// ----------------------------------------------------------------------------
#[cfg(feature = "multi_threaded")]
pub use parking_lot::MutexGuard;
#[cfg(feature = "multi_threaded")]
#[derive(Default)]
pub struct Mutex<T>(parking_lot::Mutex<T>);
#[cfg(feature = "multi_threaded")]
impl<T> Mutex<T> {
#[inline(always)]
pub fn new(val: T) -> Self {
@@ -30,6 +33,89 @@ impl<T> Mutex<T> {
}
}
// ---------------------
#[cfg(feature = "multi_threaded")]
pub use parking_lot::{RwLockReadGuard, RwLockWriteGuard};
#[cfg(feature = "multi_threaded")]
#[derive(Default)]
pub struct RwLock<T>(parking_lot::RwLock<T>);
#[cfg(feature = "multi_threaded")]
impl<T> RwLock<T> {
#[inline(always)]
pub fn new(val: T) -> Self {
Self(parking_lot::RwLock::new(val))
}
#[inline(always)]
pub fn read(&self) -> RwLockReadGuard<'_, T> {
self.0.read()
}
#[inline(always)]
pub fn write(&self) -> RwLockWriteGuard<'_, T> {
self.0.write()
}
}
// ----------------------------------------------------------------------------
// `atomic_refcell` will panic if multiple threads try to access the same value
#[cfg(not(feature = "multi_threaded"))]
pub use atomic_refcell::AtomicRefMut as MutexGuard;
#[cfg(not(feature = "multi_threaded"))]
#[derive(Default)]
pub struct Mutex<T>(atomic_refcell::AtomicRefCell<T>);
#[cfg(not(feature = "multi_threaded"))]
impl<T> Mutex<T> {
#[inline(always)]
pub fn new(val: T) -> Self {
Self(atomic_refcell::AtomicRefCell::new(val))
}
/// Panics if already locked.
#[inline(always)]
pub fn lock(&self) -> MutexGuard<'_, T> {
self.0.borrow_mut()
}
}
// ---------------------
#[cfg(not(feature = "multi_threaded"))]
pub use {
atomic_refcell::AtomicRef as RwLockReadGuard, atomic_refcell::AtomicRefMut as RwLockWriteGuard,
};
#[cfg(not(feature = "multi_threaded"))]
#[derive(Default)]
pub struct RwLock<T>(atomic_refcell::AtomicRefCell<T>);
#[cfg(not(feature = "multi_threaded"))]
impl<T> RwLock<T> {
#[inline(always)]
pub fn new(val: T) -> Self {
Self(atomic_refcell::AtomicRefCell::new(val))
}
#[inline(always)]
pub fn read(&self) -> RwLockReadGuard<'_, T> {
self.0.borrow()
}
/// Panics if already locked.
#[inline(always)]
pub fn write(&self) -> RwLockWriteGuard<'_, T> {
self.0.borrow_mut()
}
}
// ----------------------------------------------------------------------------
impl<T> Clone for Mutex<T>
where
T: Clone,
@@ -38,12 +124,3 @@ where
Self::new(self.lock().clone())
}
}
// impl<T> PartialEq for Mutex<T>
// where
// T: PartialEq,
// {
// fn eq(&self, other: &Self) -> bool {
// std::ptr::eq(self, other) || self.lock().eq(&other.lock())
// }
// }