Remove the single_threaded/multi_threaded feature flags (#1390)

Always use parking_lot for mutexes, i.e. always be multi-threaded.

Closes #1379
This commit is contained in:
Emil Ernerfeldt 2022-03-21 22:20:37 +01:00 committed by GitHub
parent 5c68edbb15
commit 15254f8235
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 21 additions and 120 deletions

View file

@ -19,7 +19,7 @@ Examples: `Vec2, Pos2, Rect, lerp, remap`
Example: `Shape::Circle { center, radius, fill, stroke }` Example: `Shape::Circle { center, radius, fill, stroke }`
Depends on `emath`, [`ab_glyph`](https://crates.io/crates/ab_glyph), [`atomic_refcell`](https://crates.io/crates/atomic_refcell), [`ahash`](https://crates.io/crates/ahash). Depends on `emath`.
### `egui_extras` ### `egui_extras`
This adds additional features on top of `egui`. This adds additional features on top of `egui`.

View file

@ -19,7 +19,11 @@ NOTE: [`epaint`](epaint/CHANGELOG.md), [`eframe`](eframe/CHANGELOG.md), [`egui_w
### Fixed 🐛 ### Fixed 🐛
* Fixed ComboBoxes always being rendered left-aligned ([#1304](https://github.com/emilk/egui/pull/1304)). * Fixed ComboBoxes always being rendered left-aligned ([#1304](https://github.com/emilk/egui/pull/1304)).
* Fixed ui code that could lead to a deadlock ([#1380](https://github.com/emilk/egui/pull/1380)) * Fixed ui code that could lead to a deadlock ([#1380](https://github.com/emilk/egui/pull/1380)).
### Removed 🔥
* Removed the `single_threaded/multi_threaded` flags - egui is now always thread-safe ([#1390](https://github.com/emilk/egui/pull/1390)).
## 0.17.0 - 2022-02-22 - Improved font selection and image handling ## 0.17.0 - 2022-02-22 - Improved font selection and image handling

7
Cargo.lock generated
View file

@ -203,12 +203,6 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "atomic_refcell"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b5e5f48b927f04e952dedc932f31995a65a0bf65ec971c74436e51bf6e970d"
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"
@ -1206,7 +1200,6 @@ version = "0.17.0"
dependencies = [ dependencies = [
"ab_glyph", "ab_glyph",
"ahash 0.7.6", "ahash 0.7.6",
"atomic_refcell",
"bytemuck", "bytemuck",
"cint", "cint",
"criterion", "criterion",

View file

@ -85,7 +85,7 @@ On Fedora Rawhide you need to run:
* Extensible: [easy to write your own widgets for egui](https://github.com/emilk/egui/blob/master/egui_demo_lib/src/apps/demo/toggle_switch.rs) * Extensible: [easy to write your own widgets for egui](https://github.com/emilk/egui/blob/master/egui_demo_lib/src/apps/demo/toggle_switch.rs)
* Modular: You should be able to use small parts of egui and combine them in new ways * 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 * Safe: there is no `unsafe` code in egui
* Minimal dependencies: [`ab_glyph`](https://crates.io/crates/ab_glyph) [`ahash`](https://crates.io/crates/ahash) [`atomic_refcell`](https://crates.io/crates/atomic_refcell), [`nohash-hasher`](https://crates.io/crates/nohash-hasher) * Minimal dependencies: [`ab_glyph`](https://crates.io/crates/ab_glyph) [`ahash`](https://crates.io/crates/ahash) [`nohash-hasher`](https://crates.io/crates/nohash-hasher) [`parking_lot`](https://crates.io/crates/parking_lot)
egui is *not* a framework. egui is a library you call into, not an environment you program for. egui is *not* a framework. egui is a library you call into, not an environment you program for.

View file

@ -45,7 +45,6 @@ serialize = ["egui/serialize", "serde"]
[dependencies] [dependencies]
egui = { version = "0.17.0", path = "../egui", default-features = false, features = [ egui = { version = "0.17.0", path = "../egui", default-features = false, features = [
"single_threaded",
"tracing", "tracing",
] } ] }
instant = { version = "0.1", features = ["wasm-bindgen"] } instant = { version = "0.1", features = ["wasm-bindgen"] }

View file

@ -20,7 +20,7 @@ all-features = true
[features] [features]
default = ["default_fonts", "single_threaded"] default = ["default_fonts"]
# add compatibility with https://crates.io/crates/cint # add compatibility with https://crates.io/crates/cint
cint = ["epaint/cint"] cint = ["epaint/cint"]
@ -46,11 +46,6 @@ persistence = ["serde", "epaint/serialize", "ron"]
# implement serde on most types. # implement serde on most types.
serialize = ["serde", "epaint/serialize"] serialize = ["serde", "epaint/serialize"]
# multi_threaded is only needed if you plan to use the same egui::Context
# from multiple threads. It comes with a minor performance impact.
single_threaded = ["epaint/single_threaded"]
multi_threaded = ["epaint/multi_threaded"]
[dependencies] [dependencies]
epaint = { version = "0.17.0", path = "../epaint", default-features = false } epaint = { version = "0.17.0", path = "../epaint", default-features = false }

View file

@ -27,9 +27,7 @@ svg = ["resvg", "tiny-skia", "usvg"]
[dependencies] [dependencies]
egui = { version = "0.17.0", path = "../egui", default-features = false, features = [ egui = { version = "0.17.0", path = "../egui", default-features = false }
"single_threaded",
] }
parking_lot = "0.12" parking_lot = "0.12"
# Optional dependencies: # Optional dependencies:
@ -37,7 +35,7 @@ parking_lot = "0.12"
# Add support for loading images with the `image` crate. # Add support for loading images with the `image` crate.
# You also need to ALSO opt-in to the image formats you want to support, like so: # You also need to ALSO opt-in to the image formats you want to support, like so:
# image = { version = "0.24", features = ["jpeg", "png"] } # image = { version = "0.24", features = ["jpeg", "png"] }
image = { version = "0.24", optional = true, default-features = false, features = [] } image = { version = "0.24", optional = true, default-features = false }
# svg feature # svg feature
resvg = { version = "0.22", optional = true } resvg = { version = "0.22", optional = true }

View file

@ -47,7 +47,6 @@ screen_reader = ["egui-winit/screen_reader"]
[dependencies] [dependencies]
egui = { version = "0.17.0", path = "../egui", default-features = false, features = [ egui = { version = "0.17.0", path = "../egui", default-features = false, features = [
"convert_bytemuck", "convert_bytemuck",
"single_threaded",
] } ] }
egui-winit = { version = "0.17.0", path = "../egui-winit", default-features = false } egui-winit = { version = "0.17.0", path = "../egui-winit", default-features = false }

View file

@ -57,7 +57,6 @@ winit = ["egui-winit", "glutin"]
[dependencies] [dependencies]
egui = { version = "0.17.0", path = "../egui", default-features = false, features = [ egui = { version = "0.17.0", path = "../egui", default-features = false, features = [
"convert_bytemuck", "convert_bytemuck",
"single_threaded",
] } ] }
epi = { version = "0.17.0", path = "../epi", optional = true } epi = { version = "0.17.0", path = "../epi", optional = true }

View file

@ -43,7 +43,6 @@ screen_reader = ["tts"]
[dependencies] [dependencies]
egui = { version = "0.17.0", path = "../egui", default-features = false, features = [ egui = { version = "0.17.0", path = "../egui", default-features = false, features = [
"convert_bytemuck", "convert_bytemuck",
"single_threaded",
"tracing", "tracing",
] } ] }
egui_glow = { version = "0.17.0", path = "../egui_glow", default-features = false } egui_glow = { version = "0.17.0", path = "../egui_glow", default-features = false }

View file

@ -4,6 +4,7 @@ All notable changes to the epaint crate will be documented in this file.
## Unreleased ## Unreleased
* Add `Shape::Callback` for backend-specific painting ([#1351](https://github.com/emilk/egui/pull/1351)). * Add `Shape::Callback` for backend-specific painting ([#1351](https://github.com/emilk/egui/pull/1351)).
* Removed the `single_threaded/multi_threaded` flags - epaint is now always thread-safe ([#1390](https://github.com/emilk/egui/pull/1390)).
## 0.17.0 - 2022-02-22 ## 0.17.0 - 2022-02-22

View file

@ -27,7 +27,7 @@ all-features = true
[features] [features]
default = ["default_fonts", "multi_threaded"] default = ["default_fonts"]
# implement bytemuck on most types. # implement bytemuck on most types.
convert_bytemuck = ["bytemuck", "emath/bytemuck"] convert_bytemuck = ["bytemuck", "emath/bytemuck"]
@ -47,23 +47,16 @@ mint = ["emath/mint"]
# implement serde on most types. # implement serde on most types.
serialize = ["serde", "ahash/serde", "emath/serde"] serialize = ["serde", "ahash/serde", "emath/serde"]
single_threaded = ["atomic_refcell"]
# Only needed if you plan to use the same fonts from multiple threads.
# It comes with a minor performance impact.
multi_threaded = ["parking_lot"]
[dependencies] [dependencies]
emath = { version = "0.17.0", path = "../emath" } emath = { version = "0.17.0", path = "../emath" }
ab_glyph = "0.2.11" ab_glyph = "0.2.11"
ahash = { version = "0.7", default-features = false, features = ["std"] } ahash = { version = "0.7", default-features = false, features = ["std"] }
atomic_refcell = { version = "0.1", optional = true } # Used instead of parking_lot when you are always using epaint in a single thread. About as fast as parking_lot. Panics on multi-threaded use.
bytemuck = { version = "1.7.2", optional = true, features = ["derive"] } bytemuck = { version = "1.7.2", optional = true, features = ["derive"] }
cint = { version = "^0.2.2", optional = true } cint = { version = "^0.2.2", optional = true }
nohash-hasher = "0.2" nohash-hasher = "0.2"
parking_lot = { version = "0.12", optional = true } # Using parking_lot over std::sync::Mutex gives 50% speedups in some real-world scenarios. parking_lot = "0.12" # Using parking_lot over std::sync::Mutex gives 50% speedups in some real-world scenarios.
serde = { version = "1", optional = true, features = ["derive", "rc"] } serde = { version = "1", optional = true, features = ["derive", "rc"] }
[dev-dependencies] [dev-dependencies]

View file

@ -1,16 +1,10 @@
//! Helper module that wraps some Mutex types with different implementations. //! Helper module that wraps some Mutex types with different implementations.
//!
//! When the `single_threaded` feature is on the mutexes will panic when locked from different threads.
#[cfg(not(any(feature = "single_threaded", feature = "multi_threaded")))]
compile_error!("Either feature \"single_threaded\" or \"multi_threaded\" must be enabled.");
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#[cfg(feature = "multi_threaded")]
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
mod mutex_impl { mod mutex_impl {
/// Provides interior mutability. Only thread-safe if the `multi_threaded` feature is enabled. /// Provides interior mutability.
#[derive(Default)] #[derive(Default)]
pub struct Mutex<T>(parking_lot::Mutex<T>); pub struct Mutex<T>(parking_lot::Mutex<T>);
@ -30,10 +24,9 @@ mod mutex_impl {
} }
} }
#[cfg(feature = "multi_threaded")]
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
mod mutex_impl { mod mutex_impl {
/// Provides interior mutability. Only thread-safe if the `multi_threaded` feature is enabled. /// Provides interior mutability.
#[derive(Default)] #[derive(Default)]
pub struct Mutex<T>(parking_lot::Mutex<T>); pub struct Mutex<T>(parking_lot::Mutex<T>);
@ -111,7 +104,6 @@ mod mutex_impl {
} }
} }
#[cfg(feature = "multi_threaded")]
mod rw_lock_impl { mod rw_lock_impl {
/// The lock you get from [`RwLock::read`]. /// The lock you get from [`RwLock::read`].
pub use parking_lot::MappedRwLockReadGuard as RwLockReadGuard; pub use parking_lot::MappedRwLockReadGuard as RwLockReadGuard;
@ -119,7 +111,7 @@ mod rw_lock_impl {
/// The lock you get from [`RwLock::write`]. /// The lock you get from [`RwLock::write`].
pub use parking_lot::MappedRwLockWriteGuard as RwLockWriteGuard; pub use parking_lot::MappedRwLockWriteGuard as RwLockWriteGuard;
/// Provides interior mutability. Only thread-safe if the `multi_threaded` feature is enabled. /// Provides interior mutability.
#[derive(Default)] #[derive(Default)]
pub struct RwLock<T>(parking_lot::RwLock<T>); pub struct RwLock<T>(parking_lot::RwLock<T>);
@ -141,79 +133,12 @@ mod rw_lock_impl {
} }
} }
#[cfg(feature = "multi_threaded")]
mod arc_impl { mod arc_impl {
pub use std::sync::Arc; pub use std::sync::Arc;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#[cfg(not(feature = "multi_threaded"))]
mod mutex_impl {
// `atomic_refcell` will panic if multiple threads try to access the same value
/// Provides interior mutability. Only thread-safe if the `multi_threaded` feature is enabled.
#[derive(Default)]
pub struct Mutex<T>(atomic_refcell::AtomicRefCell<T>);
/// The lock you get from [`Mutex`].
pub use atomic_refcell::AtomicRefMut as MutexGuard;
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"))]
mod rw_lock_impl {
// `atomic_refcell` will panic if multiple threads try to access the same value
/// The lock you get from [`RwLock::read`].
pub use atomic_refcell::AtomicRef as RwLockReadGuard;
/// The lock you get from [`RwLock::write`].
pub use atomic_refcell::AtomicRefMut as RwLockWriteGuard;
/// Provides interior mutability. Only thread-safe if the `multi_threaded` feature is enabled.
#[derive(Default)]
pub struct RwLock<T>(atomic_refcell::AtomicRefCell<T>);
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()
}
}
}
#[cfg(not(feature = "multi_threaded"))]
mod arc_impl {
// pub use std::rc::Rc as Arc; // TODO(emilk): optimize single threaded code by using `Rc` instead of `Arc`.
pub use std::sync::Arc;
}
// ----------------------------------------------------------------------------
pub use arc_impl::Arc; pub use arc_impl::Arc;
pub use mutex_impl::{Mutex, MutexGuard}; pub use mutex_impl::{Mutex, MutexGuard};
pub use rw_lock_impl::{RwLock, RwLockReadGuard, RwLockWriteGuard}; pub use rw_lock_impl::{RwLock, RwLockReadGuard, RwLockWriteGuard};

View file

@ -28,9 +28,7 @@ persistence = ["ron", "serde", "egui/persistence"]
[dependencies] [dependencies]
egui = { version = "0.17.0", path = "../egui", default-features = false, features = [ egui = { version = "0.17.0", path = "../egui", default-features = false }
"single_threaded",
] }
glow = "0.11" glow = "0.11"
tracing = "0.1" tracing = "0.1"

View file

@ -20,17 +20,15 @@ cargo doc -p egui_web --target wasm32-unknown-unknown --lib --no-deps --all-feat
cargo doc --document-private-items --no-deps --all-features cargo doc --document-private-items --no-deps --all-features
(cd emath && cargo check --no-default-features) (cd emath && cargo check --no-default-features)
(cd epaint && cargo check --no-default-features --features "single_threaded") (cd epaint && cargo check --no-default-features)
(cd epaint && cargo check --no-default-features --features "multi_threaded") (cd epaint && cargo check --no-default-features --release)
(cd epaint && cargo check --no-default-features --features "single_threaded" --release) (cd egui && cargo check --no-default-features --features "serialize")
(cd epaint && cargo check --no-default-features --features "multi_threaded" --release)
(cd egui && cargo check --no-default-features --features "multi_threaded,serialize")
(cd eframe && cargo check --no-default-features) (cd eframe && cargo check --no-default-features)
(cd epi && cargo check --no-default-features) (cd epi && cargo check --no-default-features)
(cd egui_demo_lib && cargo check --no-default-features) (cd egui_demo_lib && cargo check --no-default-features)
(cd egui_extras && cargo check --no-default-features) (cd egui_extras && cargo check --no-default-features)
(cd egui_web && cargo check --no-default-features) (cd egui_web && cargo check --no-default-features)
# (cd egui-winit && cargo check --no-default-features) # we don't pick singlethreaded or multithreaded (cd egui-winit && cargo check --no-default-features)
(cd egui_glium && cargo check --no-default-features) (cd egui_glium && cargo check --no-default-features)
(cd egui_glow && cargo check --no-default-features) (cd egui_glow && cargo check --no-default-features)