ios - does dispatch_async copy internal blocks -


given following (manual reference counting):

void (^block)(void) = ^ {     nslog(@"wuttup"); }  void (^async_block)(void) = ^ {     block(); }  dispatch_async(dispatch_get_main_queue(), async_block); 

will "block" copied rather thrown off stack , destroyed?

i believe, answer yes.

the outer block asynchronously dispatched causes runtime make copy on heap block. , shown below, , described in block implementation specification - clang 3.4 documentation, inner block's imported variables copied heap.

in op's example have "imported const copy of block reference".

i'm using example in specification:

void (^existingblock)(void) = ...; void (^vv)(void) = ^{ existingblock(); } vv(); 

the specification states copy_helper , dispose_helper functions needed:

the copy_helper function passed both existing stack based pointer , pointer new heap version , should call runtime copy operation on imported fields within block.

the following example code in specification difficult decipher (and lacks description happens when outer block copied heap). anyway, appears specification tries show imported variables of inner blocks (recursively) copied raw storage area of outer block.

when outer block copied on heap, seems imported variables of inner blocks live on heap well.

well, intuitively, makes sense.

i made small test program demonstrate this: (you have debug , examine disassembly in order figure out whats going on under surface).

#import <foundation/foundation.h>   void foo(int param) {     int x0 = param;     int x1 = param + 1;     void (^existingblock)(void) = ^{         int y0 = x0;         int y1 = x1;         printf("&y0: %p\n", &y0);         printf("&y1: %p\n", &y1);         printf("&x0: %p\n", &x0);         printf("&x1: %p\n", &x1);     };      void (^vv)(void) = ^{         int y2 = x0;         int y3 = x1;         existingblock();         printf("&y2: %p\n", &y2);         printf("&y3: %p\n", &y3);         printf("&x0: %p\n", &x0);         printf("&x1: %p\n", &x1);     };      printf("stack: &x: %p\n", &x0);     printf("stack: &x: %p\n", &x1);      printf("------- on main thread -------\n");     vv();      dispatch_async(dispatch_get_global_queue(0, 0), ^{         printf("------- on thread 2 -------\n");         assert(vv);         sleep(1);         int y4 = x0;         int y5 = x1;         vv();         printf("&y4: %p\n", &y4);         printf("&y5: %p\n", &y5);         printf("&x0: %p\n", &x0);         printf("&x1: %p\n", &x1);     }); }  int main(int argc, const char * argv[]) {     @autoreleasepool {          foo(1);         sleep(2);     }     return 0; } 

the output follows:

stack: &x: 0x7fff5fbff868 stack: &x: 0x7fff5fbff864 ------- on main thread ------- &y0: 0x7fff5fbff70c &y1: 0x7fff5fbff708 &x0: 0x1001081e0 &x1: 0x1001081e4 &y2: 0x7fff5fbff76c &y3: 0x7fff5fbff768 &x0: 0x10010a588 &x1: 0x10010a58c ------- on thread 2 ------- &y0: 0x1000e5d9c &y1: 0x1000e5d98 &x0: 0x1001081e0 &x1: 0x1001081e4 &y2: 0x1000e5dfc &y3: 0x1000e5df8 &x0: 0x10010a588 &x1: 0x10010a58c &y4: 0x1000e5e6c &y5: 0x1000e5e68 &x0: 0x10010a5e8 &x1: 0x10010a5ec 

when block executed on main thread, lives on stack (as shown addresses of local , imported variables). when executed via dispatch_async runtime has copied block - including inner blocks, can seen addresses of local , imported variables of blocks.

we can set breakpoint @ copy_helper_block function, , in fact, program stops there once, in order copy block vv heap.

enter image description here


Comments

Popular posts from this blog

css - Which browser returns the correct result for getBoundingClientRect of an SVG element? -

gcc - Calling fftR4() in c from assembly -

.htaccess - Matching full URL in RewriteCond -