MacOS: implement pump_events_with_timeout internally
This layers pump_events on a pump_events_with_timeout API, like we have for Linux and Android. This is just an internal implementation detail for now but we could consider making pump_events_with_timeout public, or just making it so that pump_events() takes the timeout argument.
This commit is contained in:
parent
e5eb253698
commit
b74cee8df1
4 changed files with 138 additions and 41 deletions
|
|
@ -141,6 +141,16 @@ pub fn setup_control_flow_observers(panic_info: Weak<PanicInfo>) {
|
|||
|
||||
pub struct EventLoopWaker {
|
||||
timer: CFRunLoopTimerRef,
|
||||
|
||||
/// An arbitrary instant in the past, that will trigger an immediate wake
|
||||
/// We save this as the `next_fire_date` for consistency so we can
|
||||
/// easily check if the next_fire_date needs updating.
|
||||
start_instant: Instant,
|
||||
|
||||
/// This is what the `NextFireDate` has been set to.
|
||||
/// `None` corresponds to `waker.stop()` and `start_instant` is used
|
||||
/// for `waker.start()`
|
||||
next_fire_date: Option<Instant>,
|
||||
}
|
||||
|
||||
impl Drop for EventLoopWaker {
|
||||
|
|
@ -169,31 +179,50 @@ impl Default for EventLoopWaker {
|
|||
ptr::null_mut(),
|
||||
);
|
||||
CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopCommonModes);
|
||||
EventLoopWaker { timer }
|
||||
EventLoopWaker {
|
||||
timer,
|
||||
start_instant: Instant::now(),
|
||||
next_fire_date: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EventLoopWaker {
|
||||
pub fn stop(&mut self) {
|
||||
unsafe { CFRunLoopTimerSetNextFireDate(self.timer, std::f64::MAX) }
|
||||
if self.next_fire_date.is_some() {
|
||||
self.next_fire_date = None;
|
||||
unsafe { CFRunLoopTimerSetNextFireDate(self.timer, std::f64::MAX) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&mut self) {
|
||||
unsafe { CFRunLoopTimerSetNextFireDate(self.timer, std::f64::MIN) }
|
||||
if self.next_fire_date != Some(self.start_instant) {
|
||||
self.next_fire_date = Some(self.start_instant);
|
||||
unsafe { CFRunLoopTimerSetNextFireDate(self.timer, std::f64::MIN) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_at(&mut self, instant: Instant) {
|
||||
pub fn start_at(&mut self, instant: Option<Instant>) {
|
||||
let now = Instant::now();
|
||||
if now >= instant {
|
||||
self.start();
|
||||
} else {
|
||||
unsafe {
|
||||
let current = CFAbsoluteTimeGetCurrent();
|
||||
let duration = instant - now;
|
||||
let fsecs =
|
||||
duration.subsec_nanos() as f64 / 1_000_000_000.0 + duration.as_secs() as f64;
|
||||
CFRunLoopTimerSetNextFireDate(self.timer, current + fsecs)
|
||||
match instant {
|
||||
Some(instant) if now >= instant => {
|
||||
self.start();
|
||||
}
|
||||
Some(instant) => {
|
||||
if self.next_fire_date != Some(instant) {
|
||||
self.next_fire_date = Some(instant);
|
||||
unsafe {
|
||||
let current = CFAbsoluteTimeGetCurrent();
|
||||
let duration = instant - now;
|
||||
let fsecs = duration.subsec_nanos() as f64 / 1_000_000_000.0
|
||||
+ duration.as_secs() as f64;
|
||||
CFRunLoopTimerSetNextFireDate(self.timer, current + fsecs)
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue