Browse Source

Optimize debug builds

pull/831/head
Emil Ernerfeldt 3 years ago
parent
commit
dd50cba9a7
  1. 16
      egui/src/context.rs
  2. 6
      egui/src/id.rs
  3. 44
      epaint/src/mutex.rs

16
egui/src/context.rs

@ -199,22 +199,24 @@ impl CtxRef {
changed: false, // must be set by the widget itself changed: false, // must be set by the widget itself
}; };
let mut memory = self.memory();
if !enabled || !sense.focusable || !layer_id.allow_interaction() { if !enabled || !sense.focusable || !layer_id.allow_interaction() {
// Not interested or allowed input: // Not interested or allowed input:
self.memory().surrender_focus(id); memory.surrender_focus(id);
return response; return response;
} }
// We only want to focus labels if the screen reader is on. // We only want to focus labels if the screen reader is on.
let interested_in_focus = let interested_in_focus =
sense.interactive() || sense.focusable && self.memory().options.screen_reader; sense.interactive() || sense.focusable && memory.options.screen_reader;
if interested_in_focus { if interested_in_focus {
self.memory().interested_in_focus(id); memory.interested_in_focus(id);
} }
if sense.click if sense.click
&& response.has_focus() && memory.has_focus(response.id)
&& (self.input().key_pressed(Key::Space) || self.input().key_pressed(Key::Enter)) && (self.input().key_pressed(Key::Space) || self.input().key_pressed(Key::Enter))
{ {
// Space/enter works like a primary click for e.g. selected buttons // Space/enter works like a primary click for e.g. selected buttons
@ -224,8 +226,6 @@ impl CtxRef {
self.register_interaction_id(id, rect); self.register_interaction_id(id, rect);
if sense.click || sense.drag { if sense.click || sense.drag {
let mut memory = self.memory();
memory.interaction.click_interest |= hovered && sense.click; memory.interaction.click_interest |= hovered && sense.click;
memory.interaction.drag_interest |= hovered && sense.drag; memory.interaction.drag_interest |= hovered && sense.drag;
@ -287,8 +287,8 @@ impl CtxRef {
response.hovered &= response.is_pointer_button_down_on; // we don't hover widgets while interacting with *other* widgets response.hovered &= response.is_pointer_button_down_on; // we don't hover widgets while interacting with *other* widgets
} }
if response.has_focus() && response.clicked_elsewhere() { if memory.has_focus(response.id) && response.clicked_elsewhere() {
self.memory().surrender_focus(id); memory.surrender_focus(id);
} }
response response

6
egui/src/id.rs

@ -88,9 +88,12 @@ impl std::hash::Hasher for IdHasher {
fn write_u32(&mut self, _n: u32) { fn write_u32(&mut self, _n: u32) {
unreachable!("Invalid use of IdHasher"); unreachable!("Invalid use of IdHasher");
} }
#[inline(always)]
fn write_u64(&mut self, n: u64) { fn write_u64(&mut self, n: u64) {
self.0 = n; self.0 = n;
} }
fn write_usize(&mut self, _n: usize) { fn write_usize(&mut self, _n: usize) {
unreachable!("Invalid use of IdHasher"); unreachable!("Invalid use of IdHasher");
} }
@ -111,6 +114,7 @@ impl std::hash::Hasher for IdHasher {
unreachable!("Invalid use of IdHasher"); unreachable!("Invalid use of IdHasher");
} }
#[inline(always)]
fn finish(&self) -> u64 { fn finish(&self) -> u64 {
self.0 self.0
} }
@ -122,6 +126,8 @@ pub struct BuilIdHasher {}
impl std::hash::BuildHasher for BuilIdHasher { impl std::hash::BuildHasher for BuilIdHasher {
type Hasher = IdHasher; type Hasher = IdHasher;
#[inline(always)]
fn build_hasher(&self) -> IdHasher { fn build_hasher(&self) -> IdHasher {
IdHasher::default() IdHasher::default()
} }

44
epaint/src/mutex.rs

@ -7,6 +7,11 @@ compile_error!("Either feature \"single_threaded\" or \"multi_threaded\" must be
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/// Provides interior mutability. Only thread-safe if the `multi_threaded` feature is enabled.
#[cfg(feature = "multi_threaded")]
#[derive(Default)]
pub struct Mutex<T>(parking_lot::Mutex<T>);
/// The lock you get from [`Mutex`]. /// The lock you get from [`Mutex`].
#[cfg(feature = "multi_threaded")] #[cfg(feature = "multi_threaded")]
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
@ -17,14 +22,29 @@ pub use parking_lot::MutexGuard;
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
pub struct MutexGuard<'a, T>(parking_lot::MutexGuard<'a, T>, *const ()); pub struct MutexGuard<'a, T>(parking_lot::MutexGuard<'a, T>, *const ());
/// Provides interior mutability. Only thread-safe if the `multi_threaded` feature is enabled. #[cfg(all(debug_assertions, feature = "multi_threaded"))]
#[cfg(feature = "multi_threaded")]
#[derive(Default)] #[derive(Default)]
pub struct Mutex<T>(parking_lot::Mutex<T>); struct HeldLocks(Vec<*const ()>);
#[cfg(debug_assertions)] #[cfg(all(debug_assertions, feature = "multi_threaded"))]
impl HeldLocks {
fn insert(&mut self, lock: *const ()) {
// Very few locks will ever be held at the same time, so a linear search is fast
assert!(
!self.0.contains(&lock),
"Recursively locking a Mutex in the same thread is not supported"
);
self.0.push(lock);
}
fn remove(&mut self, lock: *const ()) {
self.0.retain(|&ptr| ptr != lock);
}
}
#[cfg(all(debug_assertions, feature = "multi_threaded"))]
thread_local! { thread_local! {
static HELD_LOCKS_TLS: std::cell::RefCell<ahash::AHashSet<*const ()>> = std::cell::RefCell::new(ahash::AHashSet::new()); static HELD_LOCKS_TLS: std::cell::RefCell<HeldLocks> = Default::default();
} }
#[cfg(feature = "multi_threaded")] #[cfg(feature = "multi_threaded")]
@ -42,12 +62,8 @@ impl<T> Mutex<T> {
let ptr = (&self.0 as *const parking_lot::Mutex<_>).cast::<()>(); let ptr = (&self.0 as *const parking_lot::Mutex<_>).cast::<()>();
// Store it in thread local storage while we have a lock guard taken out // Store it in thread local storage while we have a lock guard taken out
HELD_LOCKS_TLS.with(|locks| { HELD_LOCKS_TLS.with(|held_locks| {
if locks.borrow().contains(&ptr) { held_locks.borrow_mut().insert(ptr);
panic!("Recursively locking a Mutex in the same thread is not supported");
} else {
locks.borrow_mut().insert(ptr);
}
}); });
MutexGuard(self.0.lock(), ptr) MutexGuard(self.0.lock(), ptr)
@ -65,8 +81,8 @@ impl<T> Mutex<T> {
impl<T> Drop for MutexGuard<'_, T> { impl<T> Drop for MutexGuard<'_, T> {
fn drop(&mut self) { fn drop(&mut self) {
let ptr = self.1; let ptr = self.1;
HELD_LOCKS_TLS.with(|locks| { HELD_LOCKS_TLS.with(|held_locks| {
locks.borrow_mut().remove(&ptr); held_locks.borrow_mut().remove(ptr);
}); });
} }
} }
@ -76,6 +92,7 @@ impl<T> Drop for MutexGuard<'_, T> {
impl<T> std::ops::Deref for MutexGuard<'_, T> { impl<T> std::ops::Deref for MutexGuard<'_, T> {
type Target = T; type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.0 &self.0
} }
@ -84,6 +101,7 @@ impl<T> std::ops::Deref for MutexGuard<'_, T> {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
#[cfg(feature = "multi_threaded")] #[cfg(feature = "multi_threaded")]
impl<T> std::ops::DerefMut for MutexGuard<'_, T> { impl<T> std::ops::DerefMut for MutexGuard<'_, T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0 &mut self.0
} }

Loading…
Cancel
Save