diff --git a/examples/src/examples-common.rs b/examples/src/examples-common.rs index 715cf5151..f22be66f2 100644 --- a/examples/src/examples-common.rs +++ b/examples/src/examples-common.rs @@ -2,22 +2,66 @@ /// on the main thread in order to open windows and use OpenGL. #[cfg(target_os = "macos")] -#[link(name = "foundation", kind = "framework")] -extern "C" { - fn CFRunLoopRun(); +mod runloop { + use std::os::raw::c_void; + #[repr(C)] + pub struct CFRunLoop(*mut c_void); + + #[link(name = "foundation", kind = "framework")] + extern "C" { + fn CFRunLoopRun(); + fn CFRunLoopGetMain() -> *mut c_void; + fn CFRunLoopStop(l: *mut c_void); + } + + impl CFRunLoop { + pub fn run() { + unsafe { + CFRunLoopRun(); + } + } + + pub fn get_main() -> CFRunLoop { + unsafe { + let r = CFRunLoopGetMain(); + assert!(!r.is_null()); + CFRunLoop(r) + } + } + + pub fn stop(&self) { + unsafe { CFRunLoopStop(self.0) } + } + } + + unsafe impl Send for CFRunLoop {} } /// On macOS this launches the callback function on a thread. /// On other platforms it's just executed immediately. #[cfg(not(target_os = "macos"))] -pub fn run(main: F) { - main(); +pub fn run T + Send + 'static>(main: F) -> T +where + T: Send + 'static, +{ + main() } #[cfg(target_os = "macos")] -pub fn run(main: F) { - ::std::thread::spawn(main); - unsafe { - CFRunLoopRun(); - } +pub fn run T + Send + 'static>(main: F) -> T +where + T: Send + 'static, +{ + use std::thread; + + let l = runloop::CFRunLoop::get_main(); + let t = thread::spawn(move || { + let res = main(); + l.stop(); + res + }); + + runloop::CFRunLoop::run(); + + t.join().unwrap() } diff --git a/tutorials/src/tutorials-common.rs b/tutorials/src/tutorials-common.rs index 715cf5151..f22be66f2 100644 --- a/tutorials/src/tutorials-common.rs +++ b/tutorials/src/tutorials-common.rs @@ -2,22 +2,66 @@ /// on the main thread in order to open windows and use OpenGL. #[cfg(target_os = "macos")] -#[link(name = "foundation", kind = "framework")] -extern "C" { - fn CFRunLoopRun(); +mod runloop { + use std::os::raw::c_void; + #[repr(C)] + pub struct CFRunLoop(*mut c_void); + + #[link(name = "foundation", kind = "framework")] + extern "C" { + fn CFRunLoopRun(); + fn CFRunLoopGetMain() -> *mut c_void; + fn CFRunLoopStop(l: *mut c_void); + } + + impl CFRunLoop { + pub fn run() { + unsafe { + CFRunLoopRun(); + } + } + + pub fn get_main() -> CFRunLoop { + unsafe { + let r = CFRunLoopGetMain(); + assert!(!r.is_null()); + CFRunLoop(r) + } + } + + pub fn stop(&self) { + unsafe { CFRunLoopStop(self.0) } + } + } + + unsafe impl Send for CFRunLoop {} } /// On macOS this launches the callback function on a thread. /// On other platforms it's just executed immediately. #[cfg(not(target_os = "macos"))] -pub fn run(main: F) { - main(); +pub fn run T + Send + 'static>(main: F) -> T +where + T: Send + 'static, +{ + main() } #[cfg(target_os = "macos")] -pub fn run(main: F) { - ::std::thread::spawn(main); - unsafe { - CFRunLoopRun(); - } +pub fn run T + Send + 'static>(main: F) -> T +where + T: Send + 'static, +{ + use std::thread; + + let l = runloop::CFRunLoop::get_main(); + let t = thread::spawn(move || { + let res = main(); + l.stop(); + res + }); + + runloop::CFRunLoop::run(); + + t.join().unwrap() }