Skip to content

Commit

Permalink
Make CFRunLoopMode a safe wrapper with a lifetime.
Browse files Browse the repository at this point in the history
Fixes #648
  • Loading branch information
kevinmehall committed Dec 4, 2023
1 parent d4ce710 commit 57cbb3b
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 27 deletions.
7 changes: 2 additions & 5 deletions core-foundation/src/filedescriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,8 @@ mod test {
extern crate libc;

use super::*;
use crate::runloop::CFRunLoop;
use crate::runloop::{CFRunLoop, CFRunLoopMode};
use core_foundation_sys::base::CFOptionFlags;
use core_foundation_sys::runloop::kCFRunLoopDefaultMode;
use libc::O_RDWR;
use std::ffi::CString;
use std::os::raw::c_void;
Expand Down Expand Up @@ -157,9 +156,7 @@ mod test {
let run_loop = CFRunLoop::get_current();
let source = CFRunLoopSource::from_file_descriptor(&cf_fd, 0);
assert!(source.is_some());
unsafe {
run_loop.add_source(&source.unwrap(), kCFRunLoopDefaultMode);
}
run_loop.add_source(&source.unwrap(), CFRunLoopMode::default());

info.value = 0;
cf_fd.enable_callbacks(kCFFileDescriptorReadCallBack);
Expand Down
55 changes: 35 additions & 20 deletions core-foundation/src/runloop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#![allow(non_upper_case_globals)]

use std::marker::PhantomData;

use core_foundation_sys::base::CFIndex;
use core_foundation_sys::base::{kCFAllocatorDefault, CFOptionFlags};
pub use core_foundation_sys::runloop::*;
Expand All @@ -19,7 +21,23 @@ use crate::date::{CFAbsoluteTime, CFTimeInterval};
use crate::filedescriptor::CFFileDescriptor;
use crate::string::CFString;

pub type CFRunLoopMode = CFStringRef;
pub struct CFRunLoopMode<'a>(CFStringRef, PhantomData<&'a CFString>);

impl<'a> CFRunLoopMode<'a> {
pub fn new(s: &'a CFString) -> CFRunLoopMode<'a> {
CFRunLoopMode(s.as_concrete_TypeRef(), PhantomData)
}

#[doc(alias = "kCFRunLoopCommonModes")]
pub fn common() -> CFRunLoopMode<'static> {
unsafe { CFRunLoopMode(kCFRunLoopCommonModes, PhantomData) }
}

#[doc(alias = "kCFRunLoopDefaultMode")]
pub fn default() -> CFRunLoopMode<'static> {
unsafe { CFRunLoopMode(kCFRunLoopDefaultMode, PhantomData) }
}
}

declare_TCFType!(CFRunLoop, CFRunLoopRef);
impl_TCFType!(CFRunLoop, CFRunLoopRef, CFRunLoopGetTypeID);
Expand Down Expand Up @@ -59,15 +77,15 @@ impl CFRunLoop {
}

pub fn run_in_mode(
mode: CFStringRef,
mode: CFRunLoopMode,
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) {
match CFRunLoopRunInMode(mode.0, seconds, return_after_source_handled) {
2 => CFRunLoopRunResult::Stopped,
3 => CFRunLoopRunResult::TimedOut,
4 => CFRunLoopRunResult::HandledSource,
Expand Down Expand Up @@ -95,50 +113,50 @@ impl CFRunLoop {
}

pub fn contains_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) -> bool {
unsafe { CFRunLoopContainsTimer(self.0, timer.0, mode) != 0 }
unsafe { CFRunLoopContainsTimer(self.0, timer.0, mode.0) != 0 }
}

pub fn add_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) {
unsafe {
CFRunLoopAddTimer(self.0, timer.0, mode);
CFRunLoopAddTimer(self.0, timer.0, mode.0);
}
}

pub fn remove_timer(&self, timer: &CFRunLoopTimer, mode: CFRunLoopMode) {
unsafe {
CFRunLoopRemoveTimer(self.0, timer.0, mode);
CFRunLoopRemoveTimer(self.0, timer.0, mode.0);
}
}

pub fn contains_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) -> bool {
unsafe { CFRunLoopContainsSource(self.0, source.0, mode) != 0 }
unsafe { CFRunLoopContainsSource(self.0, source.0, mode.0) != 0 }
}

pub fn add_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) {
unsafe {
CFRunLoopAddSource(self.0, source.0, mode);
CFRunLoopAddSource(self.0, source.0, mode.0);
}
}

pub fn remove_source(&self, source: &CFRunLoopSource, mode: CFRunLoopMode) {
unsafe {
CFRunLoopRemoveSource(self.0, source.0, mode);
CFRunLoopRemoveSource(self.0, source.0, mode.0);
}
}

pub fn contains_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) -> bool {
unsafe { CFRunLoopContainsObserver(self.0, observer.0, mode) != 0 }
unsafe { CFRunLoopContainsObserver(self.0, observer.0, mode.0) != 0 }
}

pub fn add_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) {
unsafe {
CFRunLoopAddObserver(self.0, observer.0, mode);
CFRunLoopAddObserver(self.0, observer.0, mode.0);
}
}

pub fn remove_observer(&self, observer: &CFRunLoopObserver, mode: CFRunLoopMode) {
unsafe {
CFRunLoopRemoveObserver(self.0, observer.0, mode);
CFRunLoopRemoveObserver(self.0, observer.0, mode.0);
}
}
}
Expand Down Expand Up @@ -222,9 +240,8 @@ mod test {

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);
}
run_loop.add_timer(&run_loop_timer, CFRunLoopMode::default());

CFRunLoop::run_current();
let elapsed = elapsed_rx.try_recv().unwrap();
println!("wait_200_milliseconds, elapsed: {}", elapsed);
Expand Down Expand Up @@ -277,7 +294,7 @@ mod test {
};

let runloop = CFRunLoop::get_current();
runloop.add_observer(&observer, unsafe { kCFRunLoopDefaultMode });
runloop.add_observer(&observer, CFRunLoopMode::default());

let timer = CFRunLoopTimer::new(
CFDate::now().abs_time() + 1f64,
Expand All @@ -287,11 +304,9 @@ mod test {
observe_timer_popped,
null_mut(),
);
runloop.add_timer(&timer, unsafe { kCFRunLoopDefaultMode });
runloop.add_timer(&timer, CFRunLoopMode::default());

let result = unsafe {
CFRunLoop::run_in_mode(kCFRunLoopDefaultMode, Duration::from_secs(10), false)
};
let result = CFRunLoop::run_in_mode(CFRunLoopMode::default(), Duration::from_secs(10), false);

assert_eq!(result, CFRunLoopRunResult::Stopped);

Expand Down
4 changes: 2 additions & 2 deletions core-graphics/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ unsafe extern "C" fn cg_event_tap_callback_internal(

/// ```no_run
///extern crate core_foundation;
///use core_foundation::runloop::{kCFRunLoopCommonModes, CFRunLoop};
///use core_foundation::runloop::{CFRunLoop, CFRunLoopMode};
///use core_graphics::event::{CGEventTap, CGEventTapLocation, CGEventTapPlacement, CGEventTapOptions, CGEventType};
///let current = CFRunLoop::get_current();
///match CGEventTap::new(
Expand All @@ -459,7 +459,7 @@ unsafe extern "C" fn cg_event_tap_callback_internal(
/// .mach_port
/// .create_runloop_source(0)
/// .expect("Somethings is bad ");
/// current.add_source(&loop_source, kCFRunLoopCommonModes);
/// current.add_source(&loop_source, CFRunLoopMode::common());
/// tap.enable();
/// CFRunLoop::run_current();
/// },
Expand Down

0 comments on commit 57cbb3b

Please sign in to comment.