diff --git a/src/lib.rs b/src/lib.rs index f05eee6..eca877b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,7 +52,6 @@ use std::marker::PhantomData; use std::mem; use std::ops::{Deref, DerefMut}; use std::os::raw::{c_int, c_ulong, c_void}; -use std::ptr; enum Class { } @@ -236,7 +235,7 @@ concrete_block_impl!(concrete_block_invoke_args12, a: A, b: B, c: C, d: D, e: E, #[repr(C)] pub struct ConcreteBlock { base: BlockBase, - descriptor: Box>>, + descriptor: &'static BlockDescriptor, closure: F, } @@ -256,15 +255,16 @@ impl ConcreteBlock { /// correct arguments. unsafe fn with_invoke(invoke: unsafe extern fn(*mut Self, ...) -> R, closure: F) -> Self { + let descriptor = &BlockDescriptorImpl::>::DESCRIPTOR; + const BLOCK_HAS_COPY_DISPOSE: c_int = 1 << 25; ConcreteBlock { base: BlockBase { isa: &_NSConcreteStackBlock, - // 1 << 25 = BLOCK_HAS_COPY_DISPOSE - flags: 1 << 25, + flags: if descriptor.dispose_helper.is_some() { BLOCK_HAS_COPY_DISPOSE } else { 0 }, _reserved: 0, invoke: mem::transmute(invoke), }, - descriptor: Box::new(BlockDescriptor::new()), + descriptor: descriptor, closure: closure, } } @@ -308,32 +308,32 @@ impl DerefMut for ConcreteBlock { } } -unsafe extern fn block_context_dispose(block: &mut B) { +unsafe extern fn block_context_dispose(block: *mut c_void) { // Read the block onto the stack and let it drop - ptr::read(block); + block.cast::().read(); } -unsafe extern fn block_context_copy(_dst: &mut B, _src: &B) { +unsafe extern fn block_context_copy(_dst: *mut c_void, _src: *const c_void) { // The runtime memmoves the src block into the dst block, nothing to do } #[repr(C)] -struct BlockDescriptor { +struct BlockDescriptor { _reserved: c_ulong, block_size: c_ulong, - copy_helper: unsafe extern fn(&mut B, &B), - dispose_helper: unsafe extern fn(&mut B), + copy_helper: Option, + dispose_helper: Option, } -impl BlockDescriptor { - fn new() -> BlockDescriptor { - BlockDescriptor { - _reserved: 0, - block_size: mem::size_of::() as c_ulong, - copy_helper: block_context_copy::, - dispose_helper: block_context_dispose::, - } - } +struct BlockDescriptorImpl(PhantomData); + +impl BlockDescriptorImpl { + const DESCRIPTOR: BlockDescriptor = BlockDescriptor { + _reserved: 0, + block_size: mem::size_of::() as c_ulong, + copy_helper: if std::mem::needs_drop::() { Some(block_context_copy) } else { None }, + dispose_helper: if std::mem::needs_drop::() { Some(block_context_dispose::) } else { None }, + }; } #[cfg(test)]