From 3603cbaee793ff8448d8a8a434af7186c5fc5db7 Mon Sep 17 00:00:00 2001 From: mitchmindtree Date: Tue, 25 Jun 2019 17:38:54 +0200 Subject: [PATCH] Remove macOS sleep loop in favour of using `Condvar` This solution was originally posted by @HybridEidolon in #185. Sorry it took so long! I thought it might be easier to open a new PR as half of your implementation here has already been implemented in a following PR (namely, the change from an unnecessary `Vec` of callbacks to a single user callback). Closes #185. --- src/host/coreaudio/mod.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/host/coreaudio/mod.rs b/src/host/coreaudio/mod.rs index ff22983..7654653 100644 --- a/src/host/coreaudio/mod.rs +++ b/src/host/coreaudio/mod.rs @@ -28,7 +28,7 @@ use std::fmt; use std::mem; use std::os::raw::c_char; use std::ptr::null; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Condvar, Mutex}; use std::thread; use std::time::Duration; use std::slice; @@ -434,6 +434,7 @@ pub struct EventLoop { // stream to avoid streams blocking one another. user_callback: Arc>, streams: Mutex>>, + loop_cond: Arc<(Mutex, Condvar)>, } enum UserCallback { @@ -548,6 +549,7 @@ impl EventLoop { EventLoop { user_callback: Arc::new(Mutex::new(UserCallback::Inactive)), streams: Mutex::new(Vec::new()), + loop_cond: Arc::new((Mutex::new(false), Condvar::new())), } } @@ -564,11 +566,16 @@ impl EventLoop { *guard = UserCallback::Active(unsafe { mem::transmute(callback) }); } - loop { - // So the loop does not get optimised out in --release - thread::sleep(Duration::new(1u64, 0u32)); + // Wait on a condvar to notify, which should never happen. + let &(ref lock, ref cvar) = &*self.loop_cond; + let mut running = lock.lock().unwrap(); + *running = true; + while *running { + running = cvar.wait(running).unwrap(); } + unreachable!("current `EventLoop` API requires that `run` may not return"); + // It is critical that we remove the callback before returning (currently not possible). // *self.user_callback.lock().unwrap() = UserCallback::Inactive; }