DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (1aeaa33a64f9)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
// 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);

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 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 libc::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 = unsafe { CFRunLoopTimerContext {
            version: 0,
            info: &mut info as *mut _ as *mut c_void,
            retain: mem::zeroed(),
            release: mem::zeroed(),
            copyDescription: mem::zeroed(),
        } };


        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.30);
    }

    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();
    }
}