using grand central dispatch inside class method causes memory leak - iphone

I get a memory leak when the view controller calls my model class method at the line where i create my gcd queue. Any ideas?
+(void)myClassMethod {
dispatch_queue_t myQueue = dispatch_queue_create("com.mysite.page", 0); //run with leak instrument points here as culprit
dispatch_async(myQueue, ^{});
}

You should change it to ...
dispatch_queue_t myQueue = dispatch_queue_create("com.mysite.page", 0);
dispatch_async(myQueue, ^{});
dispatch_release(myQueue);
... you should call dispatch_release when you no longer need an access to the queue. And as myQueue is local variable, you must call it there.
Read dispatch_queue_create documentation:
Discussion
Blocks submitted to the queue are executed one at a time in FIFO order. Note, however, that blocks submitted to independent queues may be executed concurrently with respect to each other.
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.

The Leak tool reports where memory is allocated that no longer has any references from your code.
After that method runs, since there is nothing that has a reference to the queue you created, and dispatch_release() was never called, it's considered a leak.

Related

Deadlock with dispatch_sync

{
dispatch_queue_t myQueue = dispatch_queue_create("com.mycompany.myqueue", 0);
dispatch_sync(myQueue, ^{
//Do EXTREME PROCESSING!!!
for (int i = 0; i< 100; i++) {
[NSThread sleepForTimeInterval:.05];
NSLog(#"%i", i);
}
dispatch_sync(dispatch_get_main_queue(), ^{
[self updateLabelWhenBackgroundDone];
});
});
}
I am getting a deadlock here. According to Apple documentation
"dispatch_sync": "Submits a block to a dispatch queue for synchronous
execution. Unlike dispatch_async, this function does not return until
the block has finished. Calling this function and targeting the
current queue results in deadlock.".
However, I do the outer dispatch_sync on myQueue and then I do inner ditpatch_sync on a different queue which is `main_queue.
Can not find out the reason for the deadlock. Any comments/help are appreciated here.
If you dispatch_sync to myQueue like that and the call happens on the main thread, then dispatch_sync will, if possible, execute the block right there and not on a new worker thread like dispatch_async would. You're not guaranteed to get a separate worker thread for your queue.
The block then runs on the main thread until it hits your second dispatch_sync call, which happens to target the main queue. That queue can't be serviced, since there's already a block running on it, and that's where you end up in a deadlock.
If that's your problem, i.e. the first dispatch_sync is indeed coming from the main thread, then you should switch to dispatch_async. You wouldn't want to block the main thread with the long-running "EXTREME PROCESSING" operation.
You are calling dispatch_sync twice. The first time suspends the main thread waiting for your block to complete. The block then suspends the background thread with the second call which tries to push back to the main thread (which will never process the block from its queue because it's suspended). Both threads are now waiting for each other.
At least one of the calls needs to be dispatch_async.
I had similar problems and none of these solutions worked. I asked someone smarter than me.
My problem was I was spawning a dispatching an async worker block, and then displaying a progress window. Calls back into the main thread via
dispatch_sync(dispatch_get_main_queue(), ^{})
failed as did async calls.
The explanation was that the main thread was no longer in 'commons mode' because of the modal window. I replaced my calls to the main thread with this....
CFRunLoopPerformBlock(([[NSRunLoop mainRunLoop] getCFRunLoop]), (__bridge CFStringRef)NSModalPanelRunLoopMode, ^{
//Update UI thread.
});

How to cancel/exit/stop execution of Thread object or thread running in background in IOS

I am detaching a thread to do some operation in the background, refer the code as below
currentThread = [[NSThread alloc]initWithTarget:contactServiceselector:#selector(requestForContactBackup:)object:msisdn];
[currentThread start];
This currentThread is the pointer declared in AppDelegate.
I have a button on my view, on tap of it, the execution of background thread should stop. Refer the below code:
-(void)cancelTheRunningTasks {
if(self.currentThread !=nil) {
[currentThread cancel];
NSLog(#"IsCancelled: %d",[currentThread isCancelled]); //here Yes returns
[self removeNetworkIndicatorInView:backUpViewController.view];
}
}
Problem with the below code is that the background thread is still remains in execution.
My question would be, having the thread reference, how to cancel/stop execution/kill the background thread from main thread?
please suggest me possible solution.
Thanks.
Your background thread needs to check to see if it has been cancelled, either through the isCancelled method...
if ([[NSThread currentThread] isCancelled]) {
// do cleanup here
[NSThread exit];
}
You can't kill the thread externally because there is no way to know what state the thread might be in and, thus, killing it would produce indeterminate behavior (imagine if the thread was holding a mutex down in the allocator when it was killed... ouch).
cancel
Changes the cancelled state of the receiver to indicate that it should exit.
exit
Terminates the current thread.
Check NSThread Class Reference
For more information about cancellation and operation objects, see NSOperation Class Reference.
Note: In OS X v10.6, the behavior of the cancel method varies depending on whether the operation is currently in an operation queue. For unqueued operations, this method marks the operation as finished immediately, generating the appropriate KVO notifications. For queued operations, it simply marks the operation as ready to execute and lets the queue call its start method, which subsequently exits and results in the clearing of the operation from the queue.
I resolved the Problem. Exactly what I was want to do that I want to stop or kill the working condition of some background thread from my main Thread or some other thread. As I read the Apple documentation and some posts I concluded that we can't kill one thread from other thread because they all threads shares common memory space and resources and its is not better to kill the thread by other thread (But one process can kill the other process because no common memory space shares between two processes).
Then I got info we cant exit/kill thread like that but still we can set the cancel property of the running thread from other thread. (In code where user requested to cancel the Tasks).
So here we can set cancel property. And inside our background task code which is under execution just check whether the cancel property is set or not. (we need to monitor after a chunk of execution of code). If cancel property is set/Yes then call [Thread exit] in that background thread code and release all the memory allocated by that thread to protect memory leaks (autorelease pool will not take care here for freeing the resources).
This is How i resolved the problem.
In simple --> just set the property of the particular task u want to cancel as cancel set. (method to set cancel will be call by the thread object reference).
if(self.currentThread != nil && [currentThread isExecuting])
{
[currentThread cancel];
}
And then monitoring in your code for cancel property. If property set then exit the thread.
if([appDelegate.currentThread isCancelled])
{
[NSThread exit];
}
If someone has better solution than this please refer. Otherwise It will also work fine.

NSBlockOperation and the start method

In reviewing my code, I've been seeing that in many places I have been making the assumption that calling [NSBlockOperationInstance start]; will start this operation on the main thread. I don't know why I thought this, but I shouldn't have been so sure any way. I checked the documentation but couldn't find any explicit mention of the thread the block would run on. However, asserting assert([NSThread isMainThread]); in the main body of the block does pass every time using start, so I'm not sure if this is a coincidence. Any one have more solid understanding of how this would work?
I forgot to mention that [op start] is being called on the main thread.
OK, it all depends on where you call start(). While NSBlockOperation will farm out blocks to other threads, start() is synchronous, and will not return until all the blocks that have been given to NSBlockOperation have completed.
While NSBlockOperation will concurrently execute the blocks it is given, NSBlockOperation itself is NOT concurrent (i.e., isConcurrent is false). Thus, according to the documentation, start() will execute in its entirety in the thread of the caller to start().
Since the thread that calls start() will not return until all the blocks have executed, it makes sense to let the calling thread be involved in the thread pool that is executing the concurrent blocks. That is why you will see some blocks executing in the thread that called start().
If you are seeing a block execute in the main thread, then you must have called it from the main thread.
On a related note, if your NSBlockOperation contains a single block, than that block will always execute in the calling thread.
Remember, if you want a NSOperation to be fully concurrent, you must implement the appropriate functionality in a subclass.
Barring that, you can give any NSOperation to a NSOperationQueue, and it will execute concurrently, because the NSOperation is given to a queue, and the thread running the operation calls start().
Personally, I do not see any advantage in using NSBlockOperation over dispatch_async() unless I need to use its features. If you are only executing one block, just call
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });
If you want to utilize the features of NSBlockOperation, but you do not want to wait for them to complete in the current calling thread, it still makes sense to do this...
// Add lots of concurrent blocks
[op addExecutionBlock:^{ /*whatever*/ }];
// Execute the blocks asynchronously
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[op start];
// Now do what you want after all the concurrent blocks have completed...
// Maybe even tell the UI
dispatch_async(dispatch_get_main_queue(), ^{
// Update the UI now that all my concurrent blocks have finished.
});
});
EDIT
To address your comment to tc's answer...
If you call
op = [NSBlockOperation blockOperationWithBlock:^{assert([NSThread isMainThread])}];
[op start];
from the main thread, then there are some guarantees, and some high probabilities.
First, you are guaranteed that [op start] will run to completion in the calling thread. That's because NSBlockOperation does not override the default behavior of NSOperation that specifies it is NOT a concurrent operation.
Next, you have a very high probability that if the NSBlockOperation only has one block, that it will run in the calling thread. You have almost the same probability that the first block will run in the calling thread.
However, the above "probabilities" are not guarantees (only because the documentation does not say it). I guess, some engineer may find some reason to spin that single block to one of the concurrent queues, and just have the calling thread join on the operation that is executing in another thread... but I highly doubt that.
Anyway, maybe your confusion comes from the fact that the documentation for NSBlockOperation says it executes block concurrently, which it does. However, the operation itself is not concurrent, so the initial operation is synchronous. It will wait for all blocks to execute, and it may (or may not) execute some of them on the calling thread.
While there is no guarantee, I find it highly unlikely that a NSBlockOperation with only one block will do anything other than execute on the calling thread.
The docs specifically say
Blocks added to a block operation are dispatched with default priority to an appropriate work queue. The blocks themselves should not make any assumptions about the configuration of their execution environment.
I suspect that the following will crash:
NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{ sleep(1); }];
[op addExecutionBlock:^{assert([NSThread isMainThread]); }];
[op start];
What's wrong with simply executing the block?

Dispatch Queues with Multiple Methods ? iPhone

I am trying to learn more about dispatch queues. If I put three methods in a dispatch queue as in the code below, do they execute one after the other or all at once ?
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^ {
[activeModel release];
[mainViewController showSceneList];
[mainViewController removeTidyUpScreen];
});
How would I specify that the next should not run until the previous one is completed ?
Think of a block -- the code you submit to a dispatch queue as you have here -- as an anonymous function. So, the code you have in your block here executes in order just as if you were calling a function that contained the same calls, one method, then the next, and so on.
In your particular example, it looks like you may be doing some operations with the UI on a queue that is not the main queue. You MUST do UI operations on the main queue, because it has access to the UI. You might use dispatch_get_main_queue() instead, to be sure you're getting that queue. If you have something you want to run in the background that will not touch the UI, then using a global queue is fine, and preferred especially if not stalling the UI is important.

Grand Central Dispatch (GCD) vs. performSelector - need a better explanation

I've used both GCD and performSelectorOnMainThread:waitUntilDone in my apps, and tend to think of them as interchangeable--that is, performSelectorOnMainThread:waitUntilDone is an Obj-C wrapper to the GCD C syntax. I've been thinking of these two commands as equivalent:
dispatch_sync(dispatch_get_main_queue(), ^{ [self doit:YES]; });
[self performSelectorOnMainThread:#selector(doit:) withObject:YES waitUntilDone:YES];
Am I incorrect? That is, is there a difference of the performSelector* commands versus the GCD ones? I've read a lot of documentation on them, but have yet to see a definitive answer.
As Jacob points out, while they may appear the same, they are different things. In fact, there's a significant difference in the way that they handle sending actions to the main thread if you're already running on the main thread.
I ran into this recently, where I had a common method that sometimes was run from something on the main thread, sometimes not. In order to protect certain UI updates, I had been using -performSelectorOnMainThread: for them with no problems.
When I switched over to using dispatch_sync on the main queue, the application would deadlock whenever this method was run on the main queue. Reading the documentation on dispatch_sync, we see:
Calling this function and targeting
the current queue results in deadlock.
where for -performSelectorOnMainThread: we see
wait
A Boolean that specifies whether the
current thread blocks until after the
specified selector is performed on the
receiver on the main thread. Specify
YES to block this thread; otherwise,
specify NO to have this method return
immediately.
If the current thread is also the main
thread, and you specify YES for this
parameter, the message is delivered
and processed immediately.
I still prefer the elegance of GCD, the better compile-time checking it provides, and its greater flexibility regarding arguments, etc., so I made this little helper function to prevent deadlocks:
void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
}
Update: In response to Dave Dribin pointing out the caveats section ondispatch_get_current_queue(), I've changed to using [NSThread isMainThread] in the above code.
I then use
runOnMainQueueWithoutDeadlocking(^{
//Do stuff
});
to perform the actions I need to secure on the main thread, without worrying about what thread the original method was executed on.
performSelectorOnMainThread: does not use GCD to send messages to objects on the main thread.
Here's how the documentation says the method is implemented:
- (void) performSelectorOnMainThread:(SEL) selector withObject:(id) obj waitUntilDone:(BOOL) wait {
[[NSRunLoop mainRunLoop] performSelector:selector target:self withObject:obj order:1 modes: NSRunLoopCommonModes];
}
And on performSelector:target:withObject:order:modes:, the documentation states:
This method sets up a timer to perform the aSelector message on the current thread’s run loop at the start of the next run loop iteration. The timer is configured to run in the modes specified by the modes parameter. When the timer fires, the thread attempts to dequeue the message from the run loop and perform the selector. It succeeds if the run loop is running and in one of the specified modes; otherwise, the timer waits until the run loop is in one of those modes.
GCD's way is suppose to be more efficient and easier to handle and is only available in iOS4 onwards whereas performSelector is supported in the older and newer iOS.