mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 12:50:04 -04:00
Support multi-threaded Wasm (#3236)
Replace `atomic_refcell` with `parking_lot` on wasm32. `parking_lot` has had problems running on wasm32 before (https://github.com/emilk/egui/issues/1401) but it works these days. If we have problems again we can always switch to `std::sync::Mutex`. Closes https://github.com/emilk/egui/issues/3102
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
//! Helper module that wraps some Mutex types with different implementations.
|
||||
//! Helper module that adds extra checks when the `deadlock_detection` feature is turned on.
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(not(debug_assertions))]
|
||||
#[cfg(not(feature = "deadlock_detection"))]
|
||||
mod mutex_impl {
|
||||
/// Provides interior mutability.
|
||||
///
|
||||
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
|
||||
/// This is a thin wrapper around [`parking_lot::Mutex`], except if
|
||||
/// the feature `deadlock_detection` is turned enabled, in which case
|
||||
/// extra checks are added to detect deadlocks.
|
||||
#[derive(Default)]
|
||||
pub struct Mutex<T>(parking_lot::Mutex<T>);
|
||||
|
||||
@@ -27,12 +28,13 @@ mod mutex_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(debug_assertions)]
|
||||
#[cfg(feature = "deadlock_detection")]
|
||||
mod mutex_impl {
|
||||
/// Provides interior mutability.
|
||||
///
|
||||
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
|
||||
/// This is a thin wrapper around [`parking_lot::Mutex`], except if
|
||||
/// the feature `deadlock_detection` is turned enabled, in which case
|
||||
/// extra checks are added to detect deadlocks.
|
||||
#[derive(Default)]
|
||||
pub struct Mutex<T>(parking_lot::Mutex<T>);
|
||||
|
||||
@@ -115,7 +117,8 @@ mod mutex_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[cfg(not(feature = "deadlock_detection"))]
|
||||
mod rw_lock_impl {
|
||||
/// The lock you get from [`RwLock::read`].
|
||||
@@ -126,7 +129,9 @@ mod rw_lock_impl {
|
||||
|
||||
/// Provides interior mutability.
|
||||
///
|
||||
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
|
||||
/// This is a thin wrapper around [`parking_lot::RwLock`], except if
|
||||
/// the feature `deadlock_detection` is turned enabled, in which case
|
||||
/// extra checks are added to detect deadlocks.
|
||||
#[derive(Default)]
|
||||
pub struct RwLock<T>(parking_lot::RwLock<T>);
|
||||
|
||||
@@ -148,7 +153,6 @@ mod rw_lock_impl {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[cfg(feature = "deadlock_detection")]
|
||||
mod rw_lock_impl {
|
||||
use std::{
|
||||
@@ -246,7 +250,9 @@ mod rw_lock_impl {
|
||||
|
||||
/// Provides interior mutability.
|
||||
///
|
||||
/// Uses `parking_lot` crate on native targets, and `atomic_refcell` on `wasm32` targets.
|
||||
/// This is a thin wrapper around [`parking_lot::RwLock`], except if
|
||||
/// the feature `deadlock_detection` is turned enabled, in which case
|
||||
/// extra checks are added to detect deadlocks.
|
||||
#[derive(Default)]
|
||||
pub struct RwLock<T> {
|
||||
lock: parking_lot::RwLock<T>,
|
||||
@@ -352,80 +358,6 @@ mod rw_lock_impl {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#[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()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn into_inner(self) -> T {
|
||||
self.0.into_inner()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn into_inner(self) -> T {
|
||||
self.0.into_inner()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
pub use mutex_impl::{Mutex, MutexGuard};
|
||||
pub use rw_lock_impl::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
@@ -469,7 +401,7 @@ mod tests {
|
||||
let other_thread = {
|
||||
let one = Arc::clone(&one);
|
||||
std::thread::spawn(move || {
|
||||
let _ = one.lock();
|
||||
let _lock = one.lock();
|
||||
})
|
||||
};
|
||||
std::thread::sleep(Duration::from_millis(200));
|
||||
|
||||
Reference in New Issue
Block a user