Skip to content

Commit f84614c

Browse files
committed
Added dispatch_once and a private Once struct.
1 parent 2416117 commit f84614c

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

src/ffi.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub type dispatch_function_t = extern fn(*mut c_void);
77
// dispatch_semaphore_t
88
pub type dispatch_group_t = *mut ();
99
pub type dispatch_object_t = *mut ();
10-
// dispatch_once_t
10+
pub type dispatch_once_t = c_long;
1111
pub type dispatch_queue_t = *mut ();
1212
pub type dispatch_time_t = u64;
1313
// dispatch_source_type_t
@@ -42,7 +42,7 @@ extern {
4242
// void dispatch_apply ( size_t iterations, dispatch_queue_t queue, void (^block)(size_t) );
4343
pub fn dispatch_apply_f(iterations: size_t, queue: dispatch_queue_t, context: *mut c_void, work: extern fn(*mut c_void, size_t));
4444
// void dispatch_once ( dispatch_once_t *predicate, dispatch_block_t block );
45-
// void dispatch_once_f ( dispatch_once_t *predicate, void *context, dispatch_function_t function );
45+
pub fn dispatch_once_f(predicate: *mut dispatch_once_t, context: *mut c_void, function: dispatch_function_t);
4646

4747
// void dispatch_group_async ( dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block );
4848
pub fn dispatch_group_async_f(group: dispatch_group_t, queue: dispatch_queue_t, context: *mut c_void, work: dispatch_function_t);

src/lib.rs

+28
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ assert!(nums[0] == "2");
4444

4545
extern crate libc;
4646

47+
use std::cell::UnsafeCell;
4748
use std::ffi::{CStr, CString};
4849
use std::mem;
4950
use std::ptr;
@@ -450,6 +451,33 @@ impl Drop for GroupGuard {
450451
}
451452
}
452453

454+
#[allow(dead_code)]
455+
struct Once {
456+
predicate: UnsafeCell<dispatch_once_t>,
457+
}
458+
459+
#[allow(dead_code)]
460+
impl Once {
461+
// TODO: make this a const fn when the feature is stable
462+
pub fn new() -> Once {
463+
Once { predicate: UnsafeCell::new(0) }
464+
}
465+
466+
#[inline(always)]
467+
pub fn call_once<F>(&'static self, work: F) where F: FnOnce() {
468+
let predicate = unsafe { *self.predicate.get() };
469+
if predicate != !0 {
470+
let mut work = Some(work);
471+
let (context, work) = context_and_sync_function(&mut work);
472+
unsafe {
473+
dispatch_once_f(self.predicate.get(), context, work);
474+
}
475+
}
476+
}
477+
}
478+
479+
unsafe impl Sync for Once { }
480+
453481
#[cfg(test)]
454482
mod tests {
455483
use std::sync::{Arc, Mutex};

0 commit comments

Comments
 (0)