美文网首页
iOS 之 block(4.4)

iOS 之 block(4.4)

作者: 老猫_2017 | 来源:发表于2020-01-14 11:18 被阅读0次

本章主题,讨论 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操作

  1. 如果为空,返还null
  2. 如果是全局,返还自身
  3. 如果在堆上,增加引用计数;
  4. 如果在栈上,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 操作

相关文章

网友评论

      本文标题:iOS 之 block(4.4)

      本文链接:https://www.haomeiwen.com/subject/jtwoactx.html