rtsao
rtsao

Reputation: 199

How to make dispatch_async nil out block

I was reading this: does dispatch_async copy internal blocks

and I want to know how to get dispatch-async to nil out the block it copied onto the heap so that the block can be garbage collected.

Ok, so on the local stack, I create my block:

MyBlock aBlock = ^{
        for (int i = 0; i < 10; i++) {
            NSLog(@"holder is: %p, holder.block is %p", holder, holder.block);
            sleep(1);
        }
    };

dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, aBlock);

sleep(2);     // give the queue some time to start executing the block

The block keeps executing simply because it is the block on the heap that is copied by dispatch_async. This is all expected behavior.

So my question is....is there a way to explicitly make this block on the heap be destroyed ?

Or will ARC memory manage that block for me from the heap when the dispatch_async has finished executing, and I personally can't do anything about it ?

Thank you!

Upvotes: 0

Views: 350

Answers (3)

newacct
newacct

Reputation: 122439

For your updated question, you don't need to nil anything. The block on the heap is just like any other reference counted object. Your scope has a strong reference to it for the duration of the scope of the variable aBlock. And the asynchronous dispatch mechanism holds a strong reference to it until it has executed. When there are no strong references to it anymore, it is deallocated.

Upvotes: 0

Wain
Wain

Reputation: 119031

If you want to be able to cancel the loop you need to put a check inside and break out when the condition isn't met. That could be that your container object is now nil, or it could be the result of some method call. Just be sure that you aren't retaining or influencing the test you add by testing for it...

Upvotes: 0

poyo fever.
poyo fever.

Reputation: 752

you can add a BOOL property to the class BlockHolder for example :

@property (nonatomic, assign, getter = isCancelled) BOOL cancelled;

and inside the block add a test to check if the block is cancelled or not like this :

__block BlockHolder * holder = [[BlockHolder alloc] init];
MyBlock aBlock = ^{
        for (int i = 0; i < 10; i++) {
            if(holder.isCancelled) return;
            NSLog(@"holder is: %p, holder.block is %p", holder, holder.block);
            sleep(1);
        }
    };

and if you want to cancel the block you can set the value of cancelled to YES. I hope it will help you

Upvotes: 0

Related Questions