I'm using a dispatch_queue which is accessed through a property of its owner, like this:
@property (nonatomic, assign) dispatch_queue_t queue;
Note the assign
keyword. The queue is used throughout the objects life and thus owned by the object. I release the queue when the owning object is deallocated:
-(void)dealloc
{
dispatch_release(self.queue);
self.queue = nil;
}
How do I properly release this? Would using retain/release
work?
What happens if there is stuff pending/running on the queue while calling release?
The following is stolen from the developer documentation:
Dispatch queues and other dispatch
objects are reference-counted data
types. When you create a serial
dispatch queue, it has an initial
reference count of 1. You can use the
dispatch_retain and dispatch_release
functions to increment and decrement
that reference count as needed. When
the reference count of a queue reaches
zero, the system asynchronously
deallocates the queue.
When your application no longer needs
the dispatch queue, it should release
it with the dispatch_release function.
Any pending blocks submitted to a
queue hold a reference to that queue,
so the queue is not deallocated until
all pending blocks have completed.
Note: You do not need to retain or
release any of the global dispatch
queues, including the concurrent
dispatch queues or the main dispatch
queue. Any attempts to retain or
release the queues are ignored.
So anywhere you would use -retain use dispatch_retain and anywhere you would use -release use dispatch_release.
Dispatch queues follow the same general memory management conventions as objective-c objects. And they won't be dealloc'ed until all blocks queued are finished.
If you do want a way to shut down a dispatch queue: There's no way to cancel all enqueued blocks via any sort of API, so they always must run to completion. One way to expedite this process is to have a BOOL variable in the class managing the dispatch queue: _isValid. When you want to shut down the queue, you can set _isValid to NO. All blocks submitted to the queue should first check _isValid before doing any work.
A side comment: It may be more appropriate to use NSOperationQueue. See Chris Hanson's blog post.
One interesting thing about this is that if the blocks submitted to the queue reference the object that owns the queue (e.g. "self"), the object will not hit dealloc
until all pending blocks in the queue are completed anyway.
Here is a project that demonstrates this:
https://github.com/joshrl/GDCQueueDeallocTest
What happens if there is stuff
pending/running on the queue while
calling release?
It is safe. pending/running queue is retained from system. Calling dispatch_release just affects the retain count of the queue. See man page of dispatch_async or so forth.
setup your property like so:
@property (readwrite, strong, nonatomic) __attribute__((NSObject)) dispatch_queue_t queue;
Assign is implied and Strong will retain the queue telling ARC to treat it as an NSObject.