summaryrefslogtreecommitdiffstats
path: root/third_party/rust/core-foundation/src/runloop.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/core-foundation/src/runloop.rs')
-rw-r--r--third_party/rust/core-foundation/src/runloop.rs224
1 files changed, 224 insertions, 0 deletions
diff --git a/third_party/rust/core-foundation/src/runloop.rs b/third_party/rust/core-foundation/src/runloop.rs
new file mode 100644
index 0000000000..be06f4ec7f
--- /dev/null
+++ b/third_party/rust/core-foundation/src/runloop.rs
@@ -0,0 +1,224 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(non_upper_case_globals)]
+
+pub use core_foundation_sys::runloop::*;
+use core_foundation_sys::base::CFIndex;
+use core_foundation_sys::base::{kCFAllocatorDefault, CFOptionFlags};
+use core_foundation_sys::string::CFStringRef;
+
+use base::{TCFType};
+use date::{CFAbsoluteTime, CFTimeInterval};
+use filedescriptor::CFFileDescriptor;
+use string::{CFString};
+
+pub type CFRunLoopMode = CFStringRef;
+
+
+declare_TCFType!(CFRunLoop, CFRunLoopRef);
+impl_TCFType!(CFRunLoop, CFRunLoopRef, CFRunLoopGetTypeID);
+impl_CFTypeDescription!(CFRunLoop);
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum CFRunLoopRunResult {
+ Finished = 1,
+ Stopped = 2,
+ TimedOut = 3,
+ HandledSource = 4,
+}
+
+impl CFRunLoop {
+ pub fn get_current() -> CFRunLoop {
+ unsafe {
+ let run_loop_ref = CFRunLoopGetCurrent();
+ TCFType::wrap_under_get_rule(run_loop_ref)
+ }
+ }
+
+ pub fn get_main() -> CFRunLoop {
+ unsafe {
+ let run_loop_ref = CFRunLoopGetMain();
+ TCFType::wrap_under_get_rule(run_loop_ref)
+ }
+ }
+
+ pub fn run_current() {
+ unsafe {
+ CFRunLoopRun();
+ }
+ }
+
+ pub fn run_in_mode(
+ mode: CFStringRef,
+ duration: std::time::Duration,
+ return_after_source_handled: bool,
+ ) -> CFRunLoopRunResult {
+ let seconds = duration.as_secs_f64();
+ let return_after_source_handled = if return_after_source_handled { 1 } else { 0 };
+
+ unsafe {
+ match CFRunLoopRunInMode(mode, seconds, return_after_source_handled) {
+ 2 => CFRunLoopRunResult::Stopped,
+ 3 => CFRunLoopRunResult::TimedOut,
+ 4 => CFRunLoopRunResult::HandledSource,
+ _ => CFRunLoopRunResult::Finished,
+ }
+ }
+ }
+
+ pub fn stop(&self) {
+ unsafe {
+ CFRunLoopStop(self.0);
+ }
+ }
+
+ pub fn current_mode(&self) -> Option<String> {
+ unsafe {
+ let string_ref = CFRunLoopCopyCurrentMode(self.0);
+ if string_ref.is_null() {
+ return None;
+ }
+
+ let cf_string: CFString = TCFType::wrap_under_create_rule(string_ref);
+ Some(cf_string.to_string())
+ }
+ }
+
+ pub fn contains_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) -> bool {
+ unsafe {
+ CFRunLoopContainsTimer(self.0, timer.0, mode) != 0
+ }
+ }
+
+ pub fn add_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) {
+ unsafe {
+ CFRunLoopAddTimer(self.0, timer.0, mode);
+ }
+ }
+
+ pub fn remove_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) {
+ unsafe {
+ CFRunLoopRemoveTimer(self.0, timer.0, mode);
+ }
+ }
+
+ pub fn contains_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) -> bool {
+ unsafe {
+ CFRunLoopContainsSource(self.0, source.0, mode) != 0
+ }
+ }
+
+ pub fn add_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) {
+ unsafe {
+ CFRunLoopAddSource(self.0, source.0, mode);
+ }
+ }
+
+ pub fn remove_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) {
+ unsafe {
+ CFRunLoopRemoveSource(self.0, source.0, mode);
+ }
+ }
+
+ pub fn contains_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) -> bool {
+ unsafe {
+ CFRunLoopContainsObserver(self.0, observer.0, mode) != 0
+ }
+ }
+
+ pub fn add_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) {
+ unsafe {
+ CFRunLoopAddObserver(self.0, observer.0, mode);
+ }
+ }
+
+ pub fn remove_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) {
+ unsafe {
+ CFRunLoopRemoveObserver(self.0, observer.0, mode);
+ }
+ }
+
+}
+
+
+declare_TCFType!(CFRunLoopTimer, CFRunLoopTimerRef);
+impl_TCFType!(CFRunLoopTimer, CFRunLoopTimerRef, CFRunLoopTimerGetTypeID);
+
+impl CFRunLoopTimer {
+ pub fn new(fireDate: CFAbsoluteTime, interval: CFTimeInterval, flags: CFOptionFlags, order: CFIndex, callout: CFRunLoopTimerCallBack, context: *mut CFRunLoopTimerContext) -> CFRunLoopTimer {
+ unsafe {
+ let timer_ref = CFRunLoopTimerCreate(kCFAllocatorDefault, fireDate, interval, flags, order, callout, context);
+ TCFType::wrap_under_create_rule(timer_ref)
+ }
+ }
+}
+
+
+declare_TCFType!(CFRunLoopSource, CFRunLoopSourceRef);
+impl_TCFType!(CFRunLoopSource, CFRunLoopSourceRef, CFRunLoopSourceGetTypeID);
+
+impl CFRunLoopSource {
+ pub fn from_file_descriptor(fd: &CFFileDescriptor, order: CFIndex) -> Option<CFRunLoopSource> {
+ fd.to_run_loop_source(order)
+ }
+}
+
+declare_TCFType!(CFRunLoopObserver, CFRunLoopObserverRef);
+impl_TCFType!(CFRunLoopObserver, CFRunLoopObserverRef, CFRunLoopObserverGetTypeID);
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use date::{CFDate, CFAbsoluteTime};
+ use std::mem;
+ use std::os::raw::c_void;
+ use std::sync::mpsc;
+
+ #[test]
+ fn wait_200_milliseconds() {
+ let run_loop = CFRunLoop::get_current();
+
+ let now = CFDate::now().abs_time();
+ let (elapsed_tx, elapsed_rx) = mpsc::channel();
+ let mut info = Info {
+ start_time: now,
+ elapsed_tx,
+ };
+ let mut context = CFRunLoopTimerContext {
+ version: 0,
+ info: &mut info as *mut _ as *mut c_void,
+ retain: None,
+ release: None,
+ copyDescription: None,
+ };
+
+ let run_loop_timer = CFRunLoopTimer::new(now + 0.20f64, 0f64, 0, 0, timer_popped, &mut context);
+ unsafe {
+ run_loop.add_timer(&run_loop_timer, kCFRunLoopDefaultMode);
+ }
+ CFRunLoop::run_current();
+ let elapsed = elapsed_rx.try_recv().unwrap();
+ println!("wait_200_milliseconds, elapsed: {}", elapsed);
+ assert!(elapsed > 0.19 && elapsed < 0.35);
+ }
+
+ struct Info {
+ start_time: CFAbsoluteTime,
+ elapsed_tx: mpsc::Sender<f64>,
+ }
+
+ extern "C" fn timer_popped(_timer: CFRunLoopTimerRef, raw_info: *mut c_void) {
+ let info: *mut Info = unsafe { mem::transmute(raw_info) };
+ let now = CFDate::now().abs_time();
+ let elapsed = now - unsafe { (*info).start_time };
+ let _ = unsafe { (*info).elapsed_tx.send(elapsed) };
+ CFRunLoop::get_current().stop();
+ }
+}