Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory management with Block programming in Objective C

I was reading the following Apple documentation on completion block in dispatch queues, and I have trouble understanding part of it. The document mentions that "To prevent the queue from being released prematurely, it is critical to retain that queue initially and release it once the completion block has been dispatched." This contradicts my understanding that the block retains all the variables in its closure, which is mentioned in the Block Programming Guide.

What am I missing here? The snippet from the document is pasted below:

A completion block is just another piece of code that you dispatch to a queue at the end of your original task. The calling code typically provides the completion block as a parameter when it starts the task. All the task code has to do is submit the specified block or function to the specified queue when it finishes its work.

Listing 3-4 shows an averaging function implemented using blocks. The last two parameters to the averaging function allow the caller to specify a queue and block to use when reporting the results. After the averaging function computes its value, it passes the results to the specified block and dispatches it to the queue. To prevent the queue from being released prematurely, it is critical to retain that queue initially and release it once the completion block has been dispatched. Listing 3-4 Executing a completion callback after a task

void average_async(int *data, size_t len, dispatch_queue_t queue, void (^block)(int))
{
   // Retain the queue provided by the user to make
   // sure it does not disappear before the completion
   // block can be called.
   dispatch_retain(queue);

   // Do the work on the default concurrent queue and then
   // call the user-provided block with the results.
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
   int avg = average(data, len);
   dispatch_async(queue, ^{ block(avg);});

   // Release the user-provided queue when done
   dispatch_release(queue);
   });
}
like image 524
Evil Nodoer Avatar asked Oct 25 '22 11:10

Evil Nodoer


1 Answers

This contradicts my understanding that the block retains all the variables in its closure

It is not a contradiction, but a misunderstanding. A block retains all objective-c objects that it references. Other object types use their own retain functions instead of a standard one. Therefore, it is impossible for the runtime to know how to retain every variable a block could contain. This is why the queue needs to be retained and released manually.

like image 108
ughoavgfhw Avatar answered Oct 27 '22 11:10

ughoavgfhw