macOS RAII trace guards (#2150)

* Add TraceGuard to make tracing simpler

* Add SharedStateMutexGuard to make tracing simpler

* Add trace_scope macro

* Add missing let binding in trace_scope!
This commit is contained in:
Mads Marquart 2022-01-23 21:35:26 +01:00 committed by GitHub
parent 51bb6b751e
commit 9229e2d88b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 176 additions and 135 deletions

View file

@ -2,11 +2,11 @@ use raw_window_handle::{AppKitHandle, RawWindowHandle};
use std::{
collections::VecDeque,
convert::TryInto,
f64,
f64, ops,
os::raw::c_void,
sync::{
atomic::{AtomicBool, Ordering},
Arc, Mutex, Weak,
Arc, Mutex, MutexGuard, Weak,
},
};
@ -251,13 +251,24 @@ lazy_static! {
static ref WINDOW_CLASS: WindowClass = unsafe {
let window_superclass = class!(NSWindow);
let mut decl = ClassDecl::new("WinitWindow", window_superclass).unwrap();
pub extern "C" fn can_become_main_window(_: &Object, _: Sel) -> BOOL {
trace_scope!("canBecomeMainWindow");
YES
}
pub extern "C" fn can_become_key_window(_: &Object, _: Sel) -> BOOL {
trace_scope!("canBecomeKeyWindow");
YES
}
decl.add_method(
sel!(canBecomeMainWindow),
util::yes as extern "C" fn(&Object, Sel) -> BOOL,
can_become_main_window as extern "C" fn(&Object, Sel) -> BOOL,
);
decl.add_method(
sel!(canBecomeKeyWindow),
util::yes as extern "C" fn(&Object, Sel) -> BOOL,
can_become_key_window as extern "C" fn(&Object, Sel) -> BOOL,
);
WindowClass(decl.register())
};
@ -311,11 +322,49 @@ impl From<WindowAttributes> for SharedState {
}
}
pub(crate) struct SharedStateMutexGuard<'a> {
guard: MutexGuard<'a, SharedState>,
called_from_fn: &'static str,
}
impl<'a> SharedStateMutexGuard<'a> {
#[inline]
pub(crate) fn new(guard: MutexGuard<'a, SharedState>, called_from_fn: &'static str) -> Self {
trace!("Locked shared state in `{}`", called_from_fn);
Self {
guard,
called_from_fn,
}
}
}
impl ops::Deref for SharedStateMutexGuard<'_> {
type Target = SharedState;
#[inline]
fn deref(&self) -> &Self::Target {
self.guard.deref()
}
}
impl ops::DerefMut for SharedStateMutexGuard<'_> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.guard.deref_mut()
}
}
impl Drop for SharedStateMutexGuard<'_> {
#[inline]
fn drop(&mut self) {
trace!("Unlocked shared state in `{}`", self.called_from_fn);
}
}
pub struct UnownedWindow {
pub ns_window: IdRef, // never changes
pub ns_view: IdRef, // never changes
input_context: IdRef, // never changes
pub shared_state: Arc<Mutex<SharedState>>,
shared_state: Arc<Mutex<SharedState>>,
decorations: AtomicBool,
cursor_state: Weak<Mutex<CursorState>>,
pub inner_rect: Option<PhysicalSize<u32>>,
@ -420,6 +469,14 @@ impl UnownedWindow {
Ok((window, delegate))
}
#[track_caller]
pub(crate) fn lock_shared_state(
&self,
called_from_fn: &'static str,
) -> SharedStateMutexGuard<'_> {
SharedStateMutexGuard::new(self.shared_state.lock().unwrap(), called_from_fn)
}
fn set_style_mask_async(&self, mask: NSWindowStyleMask) {
unsafe { util::set_style_mask_async(*self.ns_window, *self.ns_view, mask) };
}
@ -530,10 +587,8 @@ impl UnownedWindow {
#[inline]
pub fn set_resizable(&self, resizable: bool) {
let fullscreen = {
trace!("Locked shared state in `set_resizable`");
let mut shared_state_lock = self.shared_state.lock().unwrap();
let mut shared_state_lock = self.lock_shared_state("set_resizable");
shared_state_lock.resizable = resizable;
trace!("Unlocked shared state in `set_resizable`");
shared_state_lock.fullscreen.is_some()
};
if !fullscreen {
@ -653,8 +708,7 @@ impl UnownedWindow {
/// user clicking on the green fullscreen button or programmatically by
/// `toggleFullScreen:`
pub(crate) fn restore_state_from_fullscreen(&self) {
trace!("Locked shared state in `restore_state_from_fullscreen`");
let mut shared_state_lock = self.shared_state.lock().unwrap();
let mut shared_state_lock = self.lock_shared_state("restore_state_from_fullscreen");
shared_state_lock.fullscreen = None;
@ -662,7 +716,6 @@ impl UnownedWindow {
let mask = self.saved_style(&mut *shared_state_lock);
drop(shared_state_lock);
trace!("Unocked shared state in `restore_state_from_fullscreen`");
self.set_style_mask_async(mask);
self.set_maximized(maximized);
@ -705,7 +758,7 @@ impl UnownedWindow {
#[inline]
pub fn fullscreen(&self) -> Option<Fullscreen> {
let shared_state_lock = self.shared_state.lock().unwrap();
let shared_state_lock = self.lock_shared_state("fullscreen");
shared_state_lock.fullscreen.clone()
}
@ -716,25 +769,20 @@ impl UnownedWindow {
#[inline]
pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
trace!("Locked shared state in `set_fullscreen`");
let mut shared_state_lock = self.shared_state.lock().unwrap();
let mut shared_state_lock = self.lock_shared_state("set_fullscreen");
if shared_state_lock.is_simple_fullscreen {
trace!("Unlocked shared state in `set_fullscreen`");
return;
}
if shared_state_lock.in_fullscreen_transition {
// We can't set fullscreen here.
// Set fullscreen after transition.
shared_state_lock.target_fullscreen = Some(fullscreen);
trace!("Unlocked shared state in `set_fullscreen`");
return;
}
let old_fullscreen = shared_state_lock.fullscreen.clone();
if fullscreen == old_fullscreen {
trace!("Unlocked shared state in `set_fullscreen`");
return;
}
trace!("Unlocked shared state in `set_fullscreen`");
drop(shared_state_lock);
// If the fullscreen is on a different monitor, we must move the window
@ -787,8 +835,7 @@ impl UnownedWindow {
if matches!(old_fullscreen, Some(Fullscreen::Borderless(_))) {
unsafe {
let app = NSApp();
trace!("Locked shared state in `set_fullscreen`");
let mut shared_state_lock = self.shared_state.lock().unwrap();
let mut shared_state_lock = self.lock_shared_state("set_fullscreen");
shared_state_lock.save_presentation_opts = Some(app.presentationOptions_());
}
}
@ -840,8 +887,7 @@ impl UnownedWindow {
}
}
trace!("Locked shared state in `set_fullscreen`");
let mut shared_state_lock = self.shared_state.lock().unwrap();
let mut shared_state_lock = self.lock_shared_state("set_fullscreen");
shared_state_lock.fullscreen = fullscreen.clone();
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
@ -884,7 +930,6 @@ impl UnownedWindow {
// that the menu bar is disabled. This is done in the window
// delegate in `window:willUseFullScreenPresentationOptions:`.
let app = NSApp();
trace!("Locked shared state in `set_fullscreen`");
shared_state_lock.save_presentation_opts = Some(app.presentationOptions_());
let presentation_options =
@ -918,7 +963,6 @@ impl UnownedWindow {
},
_ => INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst),
};
trace!("Unlocked shared state in `set_fullscreen`");
}
#[inline]
@ -927,9 +971,7 @@ impl UnownedWindow {
self.decorations.store(decorations, Ordering::Release);
let (fullscreen, resizable) = {
trace!("Locked shared state in `set_decorations`");
let shared_state_lock = self.shared_state.lock().unwrap();
trace!("Unlocked shared state in `set_decorations`");
let shared_state_lock = self.lock_shared_state("set_decorations");
(
shared_state_lock.fullscreen.is_some(),
shared_state_lock.resizable,