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:
parent
58fcf0f2a1
commit
6f5fd1b9c0
6 changed files with 104 additions and 21 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -57,6 +57,12 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
|
||||
|
||||
[[package]]
|
||||
name = "atomic_refcell"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bc31dce067eab974c815a9deb95f6217806de7b53685d7fc31f8ccf3fb2539f"
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
|
@ -579,6 +585,7 @@ name = "egui"
|
|||
version = "0.5.0"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"atomic_refcell",
|
||||
"criterion",
|
||||
"parking_lot",
|
||||
"rusttype",
|
||||
|
@ -618,7 +625,6 @@ version = "0.5.0"
|
|||
dependencies = [
|
||||
"egui",
|
||||
"js-sys",
|
||||
"parking_lot",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"wasm-bindgen",
|
||||
|
@ -853,9 +859,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -70,7 +70,7 @@ ui.label(format!("Hello '{}', age {}", name, age));
|
|||
* Modular: You should be able to use small parts of Egui and combine them in new ways
|
||||
* Safe: there is no `unsafe` code in Egui
|
||||
* Minimal dependencies
|
||||
* Egui uses [`rusttype`](https://crates.io/crates/rusttype) to render text and [`ahash`](https://crates.io/crates/ahash) + [`parking_lot`](https://crates.io/crates/parking_lot) for a speed boost.
|
||||
* [`rusttype`](https://crates.io/crates/rusttype), [`atomic_refcell`](https://crates.io/crates/atomic_refcell) and [`ahash`](https://crates.io/crates/ahash).
|
||||
|
||||
Egui is *not* a framework. Egui is a library you call into, not an environment you program for.
|
||||
|
||||
|
|
|
@ -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())
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -18,7 +18,6 @@ crate-type = ["cdylib", "rlib"]
|
|||
[dependencies]
|
||||
egui = { version = "0.5.0", path = "../egui", features = ["serde"] }
|
||||
js-sys = "0.3"
|
||||
parking_lot = { version = "0.11", features = ["wasm-bindgen"] }
|
||||
serde = "1"
|
||||
serde_json = "1"
|
||||
wasm-bindgen = "0.2"
|
||||
|
|
Loading…
Reference in a new issue