本章主题,讨论 block 的嵌套
int main(int argc, char * argv[]) {
void (^sayBye)(int) = ^(int){};
void (^myHello)(int) = ^(int x){
sayBye(x);
};
myHello(8);
}
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
static void __main_block_func_0(struct __main_block_impl_0 *__cself, int) {
}
// sayBye 声明
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
// myHello 声明
struct __main_block_impl_1 {
struct __block_impl impl;
struct __main_block_desc_1* Desc;
struct __block_impl *sayBye;
__main_block_impl_1(void *fp, struct __main_block_desc_1 *desc, void *_sayBye, int flags=0) : sayBye((struct __block_impl *)_sayBye) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_1(struct __main_block_impl_1 *__cself, int x) {
void (*sayBye)(int) = (void (*)(int))__cself->sayBye; // bound by copy
((void (*)(__block_impl *, int))((__block_impl *)sayBye)->FuncPtr)((__block_impl *)sayBye, x);
}
static void __main_block_copy_1(struct __main_block_impl_1*dst, struct __main_block_impl_1*src) {_Block_object_assign((void*)&dst->sayBye, (void*)src->sayBye, 7/*BLOCK_FIELD_IS_BLOCK*/);}
static void __main_block_dispose_1(struct __main_block_impl_1*src) {_Block_object_dispose((void*)src->sayBye, 7/*BLOCK_FIELD_IS_BLOCK*/);}
static struct __main_block_desc_1 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __main_block_impl_1*, struct __main_block_impl_1*);
void (*dispose)(struct __main_block_impl_1*);
} __main_block_desc_1_DATA = { 0, sizeof(struct __main_block_impl_1), __main_block_copy_1, __main_block_dispose_1};
int main(int argc, char * argv[]) {
void (*sayBye)(int) = ((void (*)(int))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
void (*myHello)(int) = ((void (*)(int))&__main_block_impl_1((void *)__main_block_func_1, &__main_block_desc_1_DATA, (void *)sayBye, 570425344));
((void (*)(__block_impl *, int))((__block_impl *)myHello)->FuncPtr)((__block_impl *)myHello, 8);
}
总结:可以看出block 被捕获,有 BLOCK_FIELD_IS_BLOCK 的标示,有copy, dispose 操作
block 如下copy操作
- 如果为空,返还null
- 如果是全局,返还自身
- 如果在堆上,增加引用计数;
- 如果在栈上,copy到堆上,引用计数+1 (
其实是2
),如果有copy_helper 调用它,嵌套copy
// Copy, or bump refcount, of a block. If really copying, call the copy helper if present.
void *_Block_copy(const void *arg) {
struct Block_layout *aBlock;
if (!arg) return NULL;
// The following would be better done as a switch statement
aBlock = (struct Block_layout *)arg;
if (aBlock->flags & BLOCK_NEEDS_FREE) {
// latches on high
latching_incr_int(&aBlock->flags);
return aBlock;
}
else if (aBlock->flags & BLOCK_IS_GLOBAL) {
return aBlock;
}
else {
// Its a stack block. Make a copy.
struct Block_layout *result = malloc(aBlock->descriptor->size);
if (!result) return NULL;
memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first
// reset refcount
result->flags &= ~(BLOCK_REFCOUNT_MASK|BLOCK_DEALLOCATING); // XXX not needed
result->flags |= BLOCK_NEEDS_FREE | 2; // logical refcount 1
_Block_call_copy_helper(result, aBlock);
// Set isa last so memory analysis tools see a fully-initialized object.
result->isa = _NSConcreteMallocBlock;
return result;
}
}
下面 __block 修改block
typedef void (^SayBye)(int);
int main(int argc, char * argv[]) {
SayBye sayBye = ^(int){};
__block SayBye say = sayBye;
void (^myHello)(int) = ^(int x){
say(x);
};
myHello(8);
}
// myHello 的声明
struct __main_block_impl_1 {
struct __block_impl impl;
struct __main_block_desc_1* Desc;
__Block_byref_say_0 *say; // by ref
__main_block_impl_1(void *fp, struct __main_block_desc_1 *desc, __Block_byref_say_0 *_say, int flags=0) : say(_say->__forwarding) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
// desc
static struct __main_block_desc_1 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __main_block_impl_1*, struct __main_block_impl_1*);
void (*dispose)(struct __main_block_impl_1*);
} __main_block_desc_1_DATA = { 0, sizeof(struct __main_block_impl_1), __main_block_copy_1, __main_block_dispose_1};
static void __main_block_copy_1(struct __main_block_impl_1*dst, struct __main_block_impl_1*src) {_Block_object_assign((void*)&dst->say, (void*)src->say, 8/*BLOCK_FIELD_IS_BYREF*/);}
static void __main_block_dispose_1(struct __main_block_impl_1*src) {_Block_object_dispose((void*)src->say, 8/*BLOCK_FIELD_IS_BYREF*/);}
// byref
struct __Block_byref_say_0 {
void *__isa;
__Block_byref_say_0 *__forwarding;
int __flags;
int __size;
void (*__Block_byref_id_object_copy)(void*, void*);
void (*__Block_byref_id_object_dispose)(void*);
SayBye say;
};
__attribute__((__blocks__(byref))) __Block_byref_say_0 say = {(void*)0,(__Block_byref_say_0 *)&say, 33554432, sizeof(__Block_byref_say_0), __Block_byref_id_object_copy_135, __Block_byref_id_object_dispose_135, sayBye};
static void __Block_byref_id_object_copy_135(void *dst, void *src) {
_Block_object_assign((char*)dst + 40, *(void * *) ((char*)src + 40), 135);
}
static void __Block_byref_id_object_dispose_135(void *src) {
_Block_object_dispose(*(void * *) ((char*)src + 40), 135);
}
// 真正的调用
static void __main_block_func_1(struct __main_block_impl_1 *__cself, int x) {
__Block_byref_say_0 *say = __cself->say; // bound by ref
((void (*)(__block_impl *, int))((__block_impl *)(say->__forwarding->say))->FuncPtr)((__block_impl *)(say->__forwarding->say), x);
}
int main(int argc, char * argv[]) {
SayBye sayBye = ((void (*)(int))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
__attribute__((__blocks__(byref))) __Block_byref_say_0 say = {(void*)0,(__Block_byref_say_0 *)&say, 33554432, sizeof(__Block_byref_say_0), __Block_byref_id_object_copy_135, __Block_byref_id_object_dispose_135, sayBye};
void (*myHello)(int) = ((void (*)(int))&__main_block_impl_1((void *)__main_block_func_1, &__main_block_desc_1_DATA, (__Block_byref_say_0 *)&say, 570425344));
((void (*)(__block_impl *, int))((__block_impl *)myHello)->FuncPtr)((__block_impl *)myHello, 8);
}
总结:与之前讨论的对象差不多, byref,持有block, block flag 标记 BLOCK_FIELD_IS_BLOCK。
typedef void (^SayBye)(int);
int main(int argc, char * argv[]) {
SayBye sayBye = ^(int){};
__weak SayBye say = sayBye;
// Person *person = [Person new];
// Person __weak * p1 = person;
void (^myHello)(int) = ^(int x){
say(x);
};
myHello(8);
}
// 声明sayBye
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
struct __main_block_impl_1 {
struct __block_impl impl;
struct __main_block_desc_1* Desc;
__weak SayBye say;
__main_block_impl_1(void *fp, struct __main_block_desc_1 *desc, __weak SayBye _say, int flags=0) : say(_say) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_1(struct __main_block_impl_1 *__cself, int x) {
__weak SayBye say = __cself->say; // bound by copy
((void (*)(__block_impl *, int))((__block_impl *)say)->FuncPtr)((__block_impl *)say, x);
}
static void __main_block_copy_1(struct __main_block_impl_1*dst, struct __main_block_impl_1*src) {_Block_object_assign((void*)&dst->say, (void*)src->say, 7/*BLOCK_FIELD_IS_BLOCK*/);}
static void __main_block_dispose_1(struct __main_block_impl_1*src) {_Block_object_dispose((void*)src->say, 7/*BLOCK_FIELD_IS_BLOCK*/);}
static struct __main_block_desc_1 {
size_t reserved;
size_t Block_size;
void (*copy)(struct __main_block_impl_1*, struct __main_block_impl_1*);
void (*dispose)(struct __main_block_impl_1*);
} __main_block_desc_1_DATA = { 0, sizeof(struct __main_block_impl_1), __main_block_copy_1, __main_block_dispose_1};
int main(int argc, char * argv[]) {
SayBye sayBye = ((void (*)(int))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
__attribute__((objc_ownership(weak))) SayBye say = sayBye;
void (*myHello)(int) = ((void (*)(int))&__main_block_impl_1((void *)__main_block_func_1, &__main_block_desc_1_DATA, say, 570425344));
((void (*)(__block_impl *, int))((__block_impl *)myHello)->FuncPtr)((__block_impl *)myHello, 8);
}
总结:此处的捕获的block 被声明成 __weak 属性了, 依然有 copy, dispose 操作
网友评论