use std::ffi::c_void;
use std::ops::Deref;
use crate::data::{dispatch_release, dispatch_retain};
use crate::time::Time;
extern "C" {
fn dispatch_semaphore_create(value: isize) -> *mut Unmanaged;
fn dispatch_semaphore_wait(sema:*const Unmanaged, timeout: Time) -> isize;
fn dispatch_semaphore_signal(sema: *const Unmanaged) -> isize;
}
#[derive(Debug)]
#[repr(transparent)]
pub struct Unmanaged(c_void);
impl Unmanaged {
pub fn new(value: isize) -> *mut Unmanaged {
unsafe { dispatch_semaphore_create(value)}
}
unsafe fn release(&mut self) {
dispatch_release(self as *mut Unmanaged as *const Unmanaged as *const c_void)
}
pub fn wait(&self, time: Time) -> isize {
unsafe {
dispatch_semaphore_wait(self, time)
}
}
pub fn signal(&self) -> isize {
unsafe {
dispatch_semaphore_signal(self)
}
}
}
#[derive(Debug)]
pub struct Managed(*mut Unmanaged);
impl Managed {
pub fn new(value: isize) -> Self {
Self(Unmanaged::new(value))
}
}
impl Drop for Managed {
fn drop(&mut self) {
unsafe{ (&mut *(self.0)).release()};
}
}
impl Deref for Managed {
type Target = Unmanaged;
fn deref(&self) -> &Self::Target {
unsafe{&*self.0}
}
}
impl Clone for Managed {
fn clone(&self) -> Self {
unsafe{dispatch_retain(self.0 as *const c_void)};
Managed {
0: self.0
}
}
}
unsafe impl Sync for Managed {}
unsafe impl Send for Managed {}
#[test] fn test_allocation() {
let f = Unmanaged::new(0);
unsafe {
let f: &mut Unmanaged = &mut *f;
f.release()
}
}
#[test] fn test_wait() {
unsafe {
let f = Managed::new(0);
let static_f: &'static Managed = std::mem::transmute(&f);
std::thread::spawn(move || {
static_f.signal();
});
f.wait(Time::FOREVER);
let _ = f.clone();
}
}