Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use atomic_refcell instead of parking_lot for wasm32 targets #1404

Merged
merged 1 commit into from
Mar 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 7 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion eframe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,5 @@ image = { version = "0.24", default-features = false, features = [
"jpeg",
"png",
] }
parking_lot = "0.12"
poll-promise = "0.1"
rfd = "0.8"
2 changes: 1 addition & 1 deletion eframe/examples/custom_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

use eframe::egui;

use parking_lot::Mutex;
use egui::mutex::Mutex;
use std::sync::Arc;

fn main() {
Expand Down
1 change: 0 additions & 1 deletion egui_extras/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ svg = ["resvg", "tiny-skia", "usvg"]

[dependencies]
egui = { version = "0.17.0", path = "../egui", default-features = false }
parking_lot = "0.12"

# Optional dependencies:

Expand Down
2 changes: 1 addition & 1 deletion egui_extras/src/image.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use parking_lot::Mutex;
use egui::mutex::Mutex;

/// An image to be shown in egui.
///
Expand Down
1 change: 0 additions & 1 deletion egui_glow/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ epi = { version = "0.17.0", path = "../epi", optional = true }
bytemuck = "1.7"
glow = "0.11"
memoffset = "0.6"
parking_lot = "0.12"
tracing = "0.1"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
Expand Down
2 changes: 1 addition & 1 deletion egui_glow/src/epi_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 || {
event_loop_proxy.lock().send_event(RequestRepaintEvent).ok();
});
Expand Down
10 changes: 9 additions & 1 deletion epaint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,17 @@ ahash = { version = "0.7", default-features = false, features = ["std"] }
bytemuck = { version = "1.7.2", optional = true, features = ["derive"] }
cint = { version = "^0.2.2", optional = true }
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"] }

# 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]
criterion = { version = "0.3", default-features = false }

Expand Down
80 changes: 80 additions & 0 deletions epaint/src/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

// ----------------------------------------------------------------------------

#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(debug_assertions))]
mod mutex_impl {
/// Provides interior mutability.
///
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
#[derive(Default)]
pub struct Mutex<T>(parking_lot::Mutex<T>);

Expand All @@ -24,9 +27,12 @@ mod mutex_impl {
}
}

#[cfg(not(target_arch = "wasm32"))]
#[cfg(debug_assertions)]
mod mutex_impl {
/// Provides interior mutability.
///
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
#[derive(Default)]
pub struct Mutex<T>(parking_lot::Mutex<T>);

Expand Down Expand Up @@ -104,6 +110,7 @@ mod mutex_impl {
}
}

#[cfg(not(target_arch = "wasm32"))]
mod rw_lock_impl {
/// The lock you get from [`RwLock::read`].
pub use parking_lot::MappedRwLockReadGuard as RwLockReadGuard;
Expand All @@ -112,6 +119,8 @@ mod rw_lock_impl {
pub use parking_lot::MappedRwLockWriteGuard as RwLockWriteGuard;

/// Provides interior mutability.
///
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
#[derive(Default)]
pub struct RwLock<T>(parking_lot::RwLock<T>);

Expand All @@ -133,12 +142,83 @@ mod rw_lock_impl {
}
}

#[cfg(not(target_arch = "wasm32"))]
mod arc_impl {
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 mutex_impl::{Mutex, MutexGuard};
pub use rw_lock_impl::{RwLock, RwLockReadGuard, RwLockWriteGuard};
Expand Down