forked from rust-windowing/winit
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a timer to assist with waking the runloop
- Loading branch information
Showing
4 changed files
with
107 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,6 +41,8 @@ mod events_loop; | |
mod monitor; | ||
mod window; | ||
|
||
mod timer; | ||
|
||
#[cfg(not(feature="context"))] | ||
mod send_event; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
use std::mem; | ||
use libc::c_void; | ||
use core_foundation::base::*; | ||
use core_foundation::runloop::*; | ||
use core_foundation::date::*; | ||
|
||
// Encapsulates a CFRunLoopTimer that has a far-future time to fire, but which can be triggered | ||
// across threads for the purpose of waking up an event loop. | ||
pub struct Timer { | ||
timer: CFRunLoopTimerRef, | ||
} | ||
|
||
#[cfg(feature="context")] | ||
extern "C" fn timer_callback(timer: CFRunLoopTimerRef, info: *mut c_void) { | ||
// attempt to yield back to the caller | ||
use super::send_event_context::try_resume; | ||
unsafe { | ||
try_resume(1); | ||
} | ||
} | ||
|
||
#[cfg(not(feature="context"))] | ||
extern "C" fn timer_callback(timer: CFRunLoopTimerRef, info: *mut c_void) { | ||
// nothing to do | ||
} | ||
|
||
impl Timer { | ||
pub fn new() -> Timer { | ||
// default to firing every year, starting one year in the future | ||
let one_year: CFTimeInterval = 86400f64 * 365f64; | ||
let now = unsafe { CFAbsoluteTimeGetCurrent() }; | ||
let one_year_from_now = now + one_year; | ||
|
||
let mut context: CFRunLoopTimerContext = unsafe { mem::zeroed() }; | ||
|
||
// create a timer | ||
let timer = unsafe { | ||
CFRunLoopTimerCreate( | ||
kCFAllocatorDefault, | ||
one_year_from_now, // fireDate | ||
one_year, // interval | ||
0, // flags | ||
0, // order | ||
timer_callback, | ||
&mut context as *mut CFRunLoopTimerContext, | ||
) | ||
}; | ||
|
||
// add it to the runloop | ||
unsafe { | ||
CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopCommonModes); | ||
} | ||
|
||
Timer{ | ||
timer | ||
} | ||
} | ||
|
||
// Cause the timer to fire ASAP. Can be called across threads. | ||
pub fn trigger(&self) { | ||
unsafe { | ||
CFRunLoopTimerSetNextFireDate(self.timer, CFAbsoluteTimeGetCurrent()); | ||
} | ||
} | ||
} | ||
|
||
impl Drop for Timer { | ||
fn drop(&mut self) { | ||
unsafe { | ||
CFRunLoopRemoveTimer(CFRunLoopGetMain(), self.timer, kCFRunLoopCommonModes); | ||
CFRelease(self.timer as _); | ||
} | ||
} | ||
} | ||
|
||
// Rust doesn't know that __CFRunLoopTimer is thread safe, but the docs say it is | ||
unsafe impl Send for Timer {} | ||
unsafe impl Sync for Timer {} |