Skip to content

Commit 69c3c11

Browse files
authored
Auto merge of #610 - micolous:cfrunloop-send, r=jrmuizel
core-foundation: mark CFRunLoop as Send + Sync Fixes #550
2 parents c495523 + a1df338 commit 69c3c11

File tree

1 file changed

+67
-1
lines changed

1 file changed

+67
-1
lines changed

core-foundation/src/runloop.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ declare_TCFType!(CFRunLoop, CFRunLoopRef);
2626
impl_TCFType!(CFRunLoop, CFRunLoopRef, CFRunLoopGetTypeID);
2727
impl_CFTypeDescription!(CFRunLoop);
2828

29+
// https://github.com/servo/core-foundation-rs/issues/550
30+
unsafe impl Send for CFRunLoop {}
31+
unsafe impl Sync for CFRunLoop {}
32+
2933
#[derive(Copy, Clone, Debug, PartialEq)]
3034
pub enum CFRunLoopRunResult {
3135
Finished = 1,
@@ -176,10 +180,14 @@ impl_TCFType!(CFRunLoopObserver, CFRunLoopObserverRef, CFRunLoopObserverGetTypeI
176180
#[cfg(test)]
177181
mod test {
178182
use super::*;
179-
use date::{CFDate, CFAbsoluteTime};
183+
use base::Boolean;
184+
use date::{CFAbsoluteTime, CFDate};
180185
use std::mem;
181186
use std::os::raw::c_void;
187+
use std::ptr::null_mut;
182188
use std::sync::mpsc;
189+
use std::thread::spawn;
190+
use std::time::Duration;
183191

184192
#[test]
185193
fn wait_200_milliseconds() {
@@ -221,4 +229,62 @@ mod test {
221229
let _ = unsafe { (*info).elapsed_tx.send(elapsed) };
222230
CFRunLoop::get_current().stop();
223231
}
232+
233+
extern "C" fn observe(_: CFRunLoopObserverRef, _: CFRunLoopActivity, context: *mut c_void) {
234+
let tx: &mpsc::Sender<CFRunLoop> = unsafe { &*(context as *const _) };
235+
let _ = tx.send(CFRunLoop::get_current());
236+
}
237+
238+
extern "C" fn observe_timer_popped(_: CFRunLoopTimerRef, _: *mut c_void) {
239+
panic!("timer popped unexpectedly");
240+
}
241+
242+
#[test]
243+
fn observe_runloop() {
244+
let (tx, rx) = mpsc::channel();
245+
spawn(move || {
246+
let mut context = CFRunLoopObserverContext {
247+
version: 0,
248+
info: &tx as *const _ as *mut c_void,
249+
retain: None,
250+
release: None,
251+
copyDescription: None,
252+
};
253+
254+
let observer = unsafe {
255+
CFRunLoopObserver::wrap_under_create_rule(CFRunLoopObserverCreate(
256+
kCFAllocatorDefault,
257+
kCFRunLoopEntry,
258+
false as Boolean,
259+
0,
260+
observe,
261+
&mut context,
262+
))
263+
};
264+
265+
let runloop = CFRunLoop::get_current();
266+
runloop.add_observer(&observer, unsafe { kCFRunLoopDefaultMode });
267+
268+
let timer = CFRunLoopTimer::new(
269+
CFDate::now().abs_time() + 1f64,
270+
0f64,
271+
0,
272+
0,
273+
observe_timer_popped,
274+
null_mut(),
275+
);
276+
runloop.add_timer(&timer, unsafe { kCFRunLoopDefaultMode });
277+
278+
let result = unsafe {
279+
CFRunLoop::run_in_mode(kCFRunLoopDefaultMode, Duration::from_secs(10), false)
280+
};
281+
282+
assert_eq!(result, CFRunLoopRunResult::Stopped);
283+
284+
drop(tx);
285+
});
286+
287+
let runloop: CFRunLoop = rx.recv().unwrap();
288+
runloop.stop();
289+
}
224290
}

0 commit comments

Comments
 (0)