Use atomic_refcell instead of parking_lot for wasm32 targets (#1404)

Closes https://github.com/emilk/egui/issues/1401
This commit is contained in:
Emil Ernerfeldt 2022-03-22 15:34:21 +01:00 committed by GitHub
parent e5aeb1618f
commit 41b178b6ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 99 additions and 10 deletions

10
Cargo.lock generated
View file

@ -203,6 +203,12 @@ 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"
@ -987,7 +993,6 @@ dependencies = [
"epi", "epi",
"glow", "glow",
"image", "image",
"parking_lot 0.12.0",
"poll-promise", "poll-promise",
"rfd", "rfd",
] ]
@ -1057,7 +1062,6 @@ version = "0.17.0"
dependencies = [ dependencies = [
"egui", "egui",
"image", "image",
"parking_lot 0.12.0",
"resvg", "resvg",
"tiny-skia", "tiny-skia",
"usvg", "usvg",
@ -1086,7 +1090,6 @@ dependencies = [
"glow", "glow",
"glutin", "glutin",
"memoffset", "memoffset",
"parking_lot 0.12.0",
"tracing", "tracing",
"wasm-bindgen", "wasm-bindgen",
"web-sys", "web-sys",
@ -1200,6 +1203,7 @@ 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

@ -71,6 +71,5 @@ image = { version = "0.24", default-features = false, features = [
"jpeg", "jpeg",
"png", "png",
] } ] }
parking_lot = "0.12"
poll-promise = "0.1" poll-promise = "0.1"
rfd = "0.8" rfd = "0.8"

View file

@ -11,7 +11,7 @@
use eframe::egui; use eframe::egui;
use parking_lot::Mutex; use egui::mutex::Mutex;
use std::sync::Arc; use std::sync::Arc;
fn main() { fn main() {

View file

@ -28,7 +28,6 @@ svg = ["resvg", "tiny-skia", "usvg"]
[dependencies] [dependencies]
egui = { version = "0.17.0", path = "../egui", default-features = false } egui = { version = "0.17.0", path = "../egui", default-features = false }
parking_lot = "0.12"
# Optional dependencies: # Optional dependencies:

View file

@ -1,4 +1,4 @@
use parking_lot::Mutex; use egui::mutex::Mutex;
/// An image to be shown in egui. /// An image to be shown in egui.
/// ///

View file

@ -63,7 +63,6 @@ epi = { version = "0.17.0", path = "../epi", optional = true }
bytemuck = "1.7" bytemuck = "1.7"
glow = "0.11" glow = "0.11"
memoffset = "0.6" memoffset = "0.6"
parking_lot = "0.12"
tracing = "0.1" tracing = "0.1"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies] [target.'cfg(not(target_arch = "wasm32"))'.dependencies]

View file

@ -54,7 +54,7 @@ pub fn run(app_name: &str, native_options: &epi::NativeOptions, app_creator: epi
); );
{ {
let event_loop_proxy = parking_lot::Mutex::new(event_loop.create_proxy()); let event_loop_proxy = egui::mutex::Mutex::new(event_loop.create_proxy());
integration.egui_ctx.set_request_repaint_callback(move || { integration.egui_ctx.set_request_repaint_callback(move || {
event_loop_proxy.lock().send_event(RequestRepaintEvent).ok(); event_loop_proxy.lock().send_event(RequestRepaintEvent).ok();
}); });

View file

@ -56,9 +56,17 @@ ahash = { version = "0.7", default-features = false, features = ["std"] }
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 = "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"] }
# native:
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
parking_lot = "0.12" # Using parking_lot over std::sync::Mutex gives 50% speedups in some real-world scenarios.
# web:
[target.'cfg(target_arch = "wasm32")'.dependencies]
atomic_refcell = "0.1" # Used instead of parking_lot on on wasm. See https://github.com/emilk/egui/issues/1401
[dev-dependencies] [dev-dependencies]
criterion = { version = "0.3", default-features = false } criterion = { version = "0.3", default-features = false }

View file

@ -2,9 +2,12 @@
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
mod mutex_impl { mod mutex_impl {
/// Provides interior mutability. /// Provides interior mutability.
///
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
#[derive(Default)] #[derive(Default)]
pub struct Mutex<T>(parking_lot::Mutex<T>); pub struct Mutex<T>(parking_lot::Mutex<T>);
@ -24,9 +27,12 @@ mod mutex_impl {
} }
} }
#[cfg(not(target_arch = "wasm32"))]
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
mod mutex_impl { mod mutex_impl {
/// Provides interior mutability. /// Provides interior mutability.
///
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
#[derive(Default)] #[derive(Default)]
pub struct Mutex<T>(parking_lot::Mutex<T>); pub struct Mutex<T>(parking_lot::Mutex<T>);
@ -104,6 +110,7 @@ mod mutex_impl {
} }
} }
#[cfg(not(target_arch = "wasm32"))]
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;
@ -112,6 +119,8 @@ mod rw_lock_impl {
pub use parking_lot::MappedRwLockWriteGuard as RwLockWriteGuard; pub use parking_lot::MappedRwLockWriteGuard as RwLockWriteGuard;
/// Provides interior mutability. /// Provides interior mutability.
///
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
#[derive(Default)] #[derive(Default)]
pub struct RwLock<T>(parking_lot::RwLock<T>); pub struct RwLock<T>(parking_lot::RwLock<T>);
@ -133,12 +142,83 @@ mod rw_lock_impl {
} }
} }
#[cfg(not(target_arch = "wasm32"))]
mod arc_impl { mod arc_impl {
pub use std::sync::Arc; pub use std::sync::Arc;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#[cfg(target_arch = "wasm32")]
mod mutex_impl {
// `atomic_refcell` will panic if multiple threads try to access the same value
/// Provides interior mutability.
///
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
#[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(target_arch = "wasm32")]
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.
///
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
#[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(target_arch = "wasm32")]
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};