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.
This commit is contained in:
mitchmindtree 2019-06-25 17:38:54 +02:00
parent 7e413cb660
commit 3603cbaee7
1 changed files with 11 additions and 4 deletions

View File

@ -28,7 +28,7 @@ use std::fmt;
use std::mem; use std::mem;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::ptr::null; use std::ptr::null;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Condvar, Mutex};
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use std::slice; use std::slice;
@ -434,6 +434,7 @@ pub struct EventLoop {
// stream to avoid streams blocking one another. // stream to avoid streams blocking one another.
user_callback: Arc<Mutex<UserCallback>>, user_callback: Arc<Mutex<UserCallback>>,
streams: Mutex<Vec<Option<StreamInner>>>, streams: Mutex<Vec<Option<StreamInner>>>,
loop_cond: Arc<(Mutex<bool>, Condvar)>,
} }
enum UserCallback { enum UserCallback {
@ -548,6 +549,7 @@ impl EventLoop {
EventLoop { EventLoop {
user_callback: Arc::new(Mutex::new(UserCallback::Inactive)), user_callback: Arc::new(Mutex::new(UserCallback::Inactive)),
streams: Mutex::new(Vec::new()), 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) }); *guard = UserCallback::Active(unsafe { mem::transmute(callback) });
} }
loop { // Wait on a condvar to notify, which should never happen.
// So the loop does not get optimised out in --release let &(ref lock, ref cvar) = &*self.loop_cond;
thread::sleep(Duration::new(1u64, 0u32)); 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). // It is critical that we remove the callback before returning (currently not possible).
// *self.user_callback.lock().unwrap() = UserCallback::Inactive; // *self.user_callback.lock().unwrap() = UserCallback::Inactive;
} }