Optimize debug builds
This commit is contained in:
parent
d97a369c44
commit
dd50cba9a7
3 changed files with 45 additions and 21 deletions
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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…
Reference in a new issue