Windows: Auto close HANDLE (#9429)

`HANDLE` is wrapped in a RAII struct.

Release Notes:

- N/A

Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
白山風露 2024-03-20 00:21:01 +09:00 committed by GitHub
parent 868616d62e
commit 250528d28f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 42 additions and 20 deletions

View file

@ -59,7 +59,7 @@ pub(crate) struct WindowsPlatformInner {
text_system: Arc<WindowsTextSystem>, text_system: Arc<WindowsTextSystem>,
callbacks: Mutex<Callbacks>, callbacks: Mutex<Callbacks>,
pub raw_window_handles: RwLock<SmallVec<[HWND; 4]>>, pub raw_window_handles: RwLock<SmallVec<[HWND; 4]>>,
pub(crate) dispatch_event: HANDLE, pub(crate) dispatch_event: OwnedHandle,
pub(crate) settings: RefCell<WindowsPlatformSystemSettings>, pub(crate) settings: RefCell<WindowsPlatformSystemSettings>,
} }
@ -76,12 +76,6 @@ impl WindowsPlatformInner {
} }
} }
impl Drop for WindowsPlatformInner {
fn drop(&mut self) {
unsafe { CloseHandle(self.dispatch_event) }.ok();
}
}
#[derive(Default)] #[derive(Default)]
struct Callbacks { struct Callbacks {
open_urls: Option<Box<dyn FnMut(Vec<String>)>>, open_urls: Option<Box<dyn FnMut(Vec<String>)>>,
@ -152,8 +146,9 @@ impl WindowsPlatform {
OleInitialize(None).expect("unable to initialize Windows OLE"); OleInitialize(None).expect("unable to initialize Windows OLE");
} }
let (main_sender, main_receiver) = flume::unbounded::<Runnable>(); let (main_sender, main_receiver) = flume::unbounded::<Runnable>();
let dispatch_event = unsafe { CreateEventW(None, false, false, None) }.unwrap(); let dispatch_event =
let dispatcher = Arc::new(WindowsDispatcher::new(main_sender, dispatch_event)); OwnedHandle::new(unsafe { CreateEventW(None, false, false, None) }.unwrap());
let dispatcher = Arc::new(WindowsDispatcher::new(main_sender, dispatch_event.to_raw()));
let background_executor = BackgroundExecutor::new(dispatcher.clone()); let background_executor = BackgroundExecutor::new(dispatcher.clone());
let foreground_executor = ForegroundExecutor::new(dispatcher); let foreground_executor = ForegroundExecutor::new(dispatcher);
let text_system = Arc::new(WindowsTextSystem::new()); let text_system = Arc::new(WindowsTextSystem::new());
@ -208,14 +203,15 @@ impl Platform for WindowsPlatform {
fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>) { fn run(&self, on_finish_launching: Box<dyn 'static + FnOnce()>) {
on_finish_launching(); on_finish_launching();
let dispatch_event = self.inner.dispatch_event; let dispatch_event = self.inner.dispatch_event.to_raw();
let vsync_event = unsafe { CreateEventW(None, false, false, None) }.unwrap(); let vsync_event = create_event().unwrap();
let timer_stop_event = unsafe { CreateEventW(None, false, false, None) }.unwrap(); let timer_stop_event = create_event().unwrap();
begin_vsync_timer(vsync_event, timer_stop_event); let raw_timer_stop_event = timer_stop_event.to_raw();
begin_vsync_timer(vsync_event.to_raw(), timer_stop_event);
'a: loop { 'a: loop {
let wait_result = unsafe { let wait_result = unsafe {
MsgWaitForMultipleObjects( MsgWaitForMultipleObjects(
Some(&[vsync_event, dispatch_event]), Some(&[vsync_event.to_raw(), dispatch_event]),
false, false,
INFINITE, INFINITE,
QS_ALLINPUT, QS_ALLINPUT,
@ -257,8 +253,7 @@ impl Platform for WindowsPlatform {
} }
} }
} }
end_vsync_timer(timer_stop_event); end_vsync_timer(raw_timer_stop_event);
unsafe { CloseHandle(dispatch_event) }.log_err();
let mut callbacks = self.inner.callbacks.lock(); let mut callbacks = self.inner.callbacks.lock();
if let Some(callback) = callbacks.quit.as_mut() { if let Some(callback) = callbacks.quit.as_mut() {
@ -737,15 +732,14 @@ unsafe fn show_savefile_dialog(directory: PathBuf) -> Result<IFileSaveDialog> {
Ok(dialog) Ok(dialog)
} }
fn begin_vsync_timer(vsync_event: HANDLE, timer_stop_event: HANDLE) { fn begin_vsync_timer(vsync_event: HANDLE, timer_stop_event: OwnedHandle) {
let vsync_fn = select_vsync_fn(); let vsync_fn = select_vsync_fn();
std::thread::spawn(move || { std::thread::spawn(move || {
while vsync_fn(timer_stop_event) { while vsync_fn(timer_stop_event.to_raw()) {
if unsafe { SetEvent(vsync_event) }.log_err().is_none() { if unsafe { SetEvent(vsync_event) }.log_err().is_none() {
break; break;
} }
} }
unsafe { CloseHandle(timer_stop_event) }.log_err();
}); });
} }

View file

@ -1,4 +1,5 @@
use windows::Win32::{Foundation::*, UI::WindowsAndMessaging::*}; use util::ResultExt;
use windows::Win32::{Foundation::*, System::Threading::*, UI::WindowsAndMessaging::*};
pub(crate) trait HiLoWord { pub(crate) trait HiLoWord {
fn hiword(&self) -> u16; fn hiword(&self) -> u16;
@ -69,6 +70,33 @@ pub(crate) unsafe fn set_window_long(
} }
} }
pub(crate) struct OwnedHandle(HANDLE);
impl OwnedHandle {
pub(crate) fn new(handle: HANDLE) -> Self {
Self(handle)
}
#[inline(always)]
pub(crate) fn to_raw(&self) -> HANDLE {
self.0
}
}
impl Drop for OwnedHandle {
fn drop(&mut self) {
if !self.0.is_invalid() {
unsafe { CloseHandle(self.0) }.log_err();
}
}
}
pub(crate) fn create_event() -> windows::core::Result<OwnedHandle> {
Ok(OwnedHandle::new(unsafe {
CreateEventW(None, false, false, None)?
}))
}
pub(crate) fn windows_credentials_target_name(url: &str) -> String { pub(crate) fn windows_credentials_target_name(url: &str) -> String {
format!("zed:url={}", url) format!("zed:url={}", url)
} }