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:
@@ -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
|
||||
|
||||
@@ -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},
|
||||
};
|
||||
|
||||
|
||||
@@ -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())
|
||||
// }
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user