Is Block_copy recursive?

Viewed 2203

I have some code that essentially boils down to this:

-(void)doSomethingWithBlock:(BlockTypedef)block
{
    [Foo doSomethingElseWithBlock:^() {
        block();
    }];
}

Foo doSomethingElseWithBlock: calls Block_copy and Block_release on the block that it receives. Is this also necessary at the outer scope, or will the inner Block_copy handle this?

3 Answers

Yes, this is safe. You don't need to make a copy. At the time that -[Foo doSomethingElseWithBlock:] makes a copy of your literal block, it will copy the inner block to the heap.

I wrote some test code to prove to myself that this happens; see how printer (used only in block1) is copied from the stack to the heap at the time that Block_copy(block2) is called.

#include <Block.h>
#include <dispatch/dispatch.h>
#include <stdio.h>

typedef void (^void_block)();

class ScopedPrinter {
  public:
    ScopedPrinter() {
        printf("construct %p\n", this);
    }
    ScopedPrinter(const ScopedPrinter& other) {
        printf("copy %p <- %p\n", this, &other);
    }
    ~ScopedPrinter() {
        printf("destroy %p\n", this);
    }
};

void_block invoke(void_block other) {
    printf("other %p\n", (void*)other);
    void_block block2 = ^{
        printf("other %p\n", (void*)other);
        other();
    };
    printf("block2 created\n");
    block2 = Block_copy(block2);
    printf("block2 copied\n");
    return block2;
}

void_block make_block() {
    ScopedPrinter printer;
    printf("printer created\n");
    void_block block1 = ^{
        printf("block1 %p\n", &printer);
    };
    printf("block1 created\n");
    return invoke(block1);
}

int main() {
    void_block block = make_block();
    block();
    Block_release(block);
    return 0;
}

Transcript:

construct 0x7fff6a23fa70
printer created
copy 0x7fff6a23fa50 <- 0x7fff6a23fa70
block1 created
other 0x7fff6a23fa30
block2 created
copy 0x10a700970 <- 0x7fff6a23fa50
block2 copied
destroy 0x7fff6a23fa50
destroy 0x7fff6a23fa70
other 0x10a700950
block1 0x10a700970
destroy 0x10a700970
Related