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)]