use std::os::raw::{c_int, c_ulong};
use std::ffi::c_void;
use std::mem::MaybeUninit;
#[repr(C)]
#[derive(Debug)]
#[doc(hidden)]
pub struct BlockDescriptorMany {
pub reserved: MaybeUninit<c_ulong>,
pub size: c_ulong,
pub copy_helper: extern "C" fn(dst: *mut blocksr::hidden::BlockLiteralManyEscape, src: *mut blocksr::hidden::BlockLiteralManyEscape),
pub dispose_helper: extern "C" fn(src: *mut blocksr::hidden::BlockLiteralManyEscape),
}
#[doc(hidden)]
pub static mut BLOCK_DESCRIPTOR_MANY: BlockDescriptorMany = BlockDescriptorMany {
reserved: MaybeUninit::uninit(),
size: std::mem::size_of::<BlockLiteralManyEscape>() as u64,
copy_helper: copy_helper,
dispose_helper: dispose_helper,
};
extern "C" fn dispose_helper(src: *mut blocksr::hidden::BlockLiteralManyEscape) {
println!("dispose_helper");
unsafe{((*src).dispose)(src)}
}
extern "C" fn copy_helper(_dst: *mut blocksr::hidden::BlockLiteralManyEscape, _src: *mut blocksr::hidden::BlockLiteralManyEscape) {
println!("copy_helper");
}
#[repr(C)]
#[derive(Debug)]
#[doc(hidden)]
pub struct Payload<C,E> {
pub closure: C,
pub environment: E,
}
#[repr(C)]
#[derive(Debug)]
#[doc(hidden)]
pub struct BlockLiteralManyEscape {
pub isa: *const c_void,
pub flags: c_int,
pub reserved: c_int,
pub invoke: *const c_void,
pub descriptor: *mut c_void,
pub payload: *mut c_void,
pub dispose: extern "C" fn(*mut BlockLiteralManyEscape),
}
#[macro_export]
macro_rules! many_escaping_nonreentrant(
(
$pub:vis $blockname: ident (environment: &mut $environment:ty $(,$a:ident : $A:ty)*) -> $R:ty
) => {
#[repr(transparent)]
#[derive(Debug)]
#[allow(non_camel_case_types)] $pub struct $blockname(blocksr::hidden::BlockLiteralManyEscape);
impl $blockname {
pub unsafe fn new<C,E>(environment: E, f: C) -> Self where C: FnMut(&mut E, $($A),*) -> $R + Send + 'static {
extern "C" fn invoke_thunk<G,H>(block: *mut blocksr::hidden::BlockLiteralManyEscape, $($a : $A),*) -> $R where G: FnMut(&mut H, $($A),*) -> $R + Send {
let payload_ptr = unsafe{(*block).payload} as *mut _ as *mut blocksr::hidden::Payload<G,H>;
let mut boxed_payload: Box<blocksr::hidden::Payload<G,H>> = unsafe {Box::from_raw(payload_ptr)};
let closure: &mut G = &mut boxed_payload.closure;
let environment: &mut H = &mut boxed_payload.environment;
let r = closure(environment, $($a),*);
std::mem::forget(boxed_payload);
r
}
extern "C" fn dispose_thunk<G,H>(block: *mut blocksr::hidden::BlockLiteralManyEscape) {
let payload_ptr = unsafe{(*block).payload} as *mut _ as *mut blocksr::hidden::Payload<G,H>;
let mut boxed_payload: Box<blocksr::hidden::Payload<G,H>> = unsafe {Box::from_raw(payload_ptr)};
}
let thunk_fn: *const core::ffi::c_void = invoke_thunk::<C,E> as *const core::ffi::c_void;
let payload = blocksr::hidden::Payload {
closure: f,
environment
};
let boxed_load = Box::new(payload);
let raw_load = Box::into_raw(boxed_load) as *mut _ as *mut core::ffi::c_void;
let literal = blocksr::hidden::BlockLiteralManyEscape {
isa: &blocksr::hidden::_NSConcreteStackBlock,
flags: blocksr::hidden::BLOCK_HAS_STRET | blocksr::hidden::BLOCK_HAS_COPY_DISPOSE,
reserved: std::mem::MaybeUninit::uninit().assume_init(),
invoke: thunk_fn ,
descriptor: &mut blocksr::hidden::BLOCK_DESCRIPTOR_MANY as *mut _ as *mut core::ffi::c_void,
payload: raw_load,
dispose: dispose_thunk::<C,E>,
};
$blockname(literal)
}
}
}
);
#[macro_export]
macro_rules! many_escaping_reentrant(
(
$pub:vis $blockname: ident (environment: &$environment:ty $(,$a:ident : $A:ty)*) -> $R:ty
) => {
#[repr(transparent)]
#[derive(Debug)]
#[allow(non_camel_case_types)] $pub struct $blockname(blocksr::hidden::BlockLiteralManyEscape);
impl $blockname {
pub unsafe fn new<C,E>(environment: E, f: C) -> Self where C: Fn(&E, $($A),*) -> $R + Send + 'static {
extern "C" fn invoke_thunk<G,H>(block: *mut blocksr::hidden::BlockLiteralManyEscape, $($a : $A),*) -> $R where G: Fn(&H, $($A),*) -> $R + Send {
let payload_ptr = unsafe{(*block).payload} as *mut _ as *mut blocksr::hidden::Payload<G,H>;
unsafe {
let boxed_payload: Box<blocksr::hidden::Payload<G,H>> = unsafe {Box::from_raw(payload_ptr)};
let closure: &G = &boxed_payload.closure;
let environment: &H = &boxed_payload.environment;
let r = closure(environment, $($a),*);
std::mem::forget(boxed_payload);
r
}
}
extern "C" fn dispose_thunk<G,H>(block: *mut blocksr::hidden::BlockLiteralManyEscape) {
let payload_ptr = unsafe{(*block).payload} as *mut _ as *mut blocksr::hidden::Payload<G,H>;
let mut boxed_payload: Box<blocksr::hidden::Payload<G,H>> = unsafe {Box::from_raw(payload_ptr)};
}
let thunk_fn: *const core::ffi::c_void = invoke_thunk::<C,E> as *const core::ffi::c_void;
let payload = blocksr::hidden::Payload {
closure: f,
environment
};
let boxed_load = Box::new(payload);
let raw_load = Box::into_raw(boxed_load) as *mut _ as *mut core::ffi::c_void;
let literal = blocksr::hidden::BlockLiteralManyEscape {
isa: &blocksr::hidden::_NSConcreteStackBlock,
flags: blocksr::hidden::BLOCK_HAS_STRET | blocksr::hidden::BLOCK_HAS_COPY_DISPOSE,
reserved: std::mem::MaybeUninit::uninit().assume_init(),
invoke: thunk_fn ,
descriptor: &mut blocksr::hidden::BLOCK_DESCRIPTOR_MANY as *mut _ as *mut core::ffi::c_void,
payload: raw_load,
dispose: dispose_thunk::<C,E>,
};
$blockname(literal)
}
}
}
);