From: Apple docs on managing concurrency:
NsOperation
Write a custom subclass and override one method: main. The main method gets called to perform the operation when the NSOperationQueue schedules it to run. NSOperation classes written in this way are known as non-concurrent operations, because the developer is not responsible for spawning threads—multi-threading is all handled by the super class. (Don’t be confused by the terminology: just because an operation is non-concurrent, does not mean it cannot be executed concurrently, it simply means that you don't have to handle the concurrency yourself.)
I think overriding main is the easiest way to use NSOperation, but the apple site says its non-concurrent does it mean that the nsoperations in the nsoperation queue(when only overriding main) would execute serially?
I don't want to execute my operations serially, but I want to get my operations parallel with as minimum effort as possible.
No, they will not necessarily be run serially. Just as the paragraph you quoted noted, it "does not mean it cannot be executed concurrently".
So what does determine if they can run in parallel? The NSOperationQueue and any dependencies you set up between the ops. A little later in that same document, the section entitled "Running Operations" explains:
you can specify (limit) the number of threads the queue will spawn, and
"NSOperationQueue will automatically determine how many threads it should spawn."
And in the Concurrency Programming Guide it elaborates:
In most cases, operations are executed shortly after being added to a queue, but the operation queue may delay execution of queued operations for any of several reasons. Specifically, execution may be delayed if queued operations are dependent on other operations that have not yet completed. Execution may also be delayed if the operation queue itself is suspended or is already executing its maximum number of concurrent operations.
What you do give up by using non-concurrent operations is that the operation itself isn't intended to set up new threads, etc.
I am not sure about it, but i am using "dispatch_queue_create" to create parallel processes.
Suppose if i want to do two functionalities at same time, i am using the following code. Please see if it will help you,
dispatch_queue_t queue = dispatch_queue_create("FirstOperation", 0ul);
dispatch_async(queue, ^{
//Do your functionality here
dispatch_sync(dispatch_get_main_queue(), ^{
//Do your UI updates here
});
});
dispatch_release(queue);
dispatch_queue_t queue2 = dispatch_queue_create("SecondOperation", 0ul);
dispatch_async(queue2, ^{
//Do your functionality here
dispatch_sync(dispatch_get_main_queue(), ^{
//Do your UI updates here
});
});
dispatch_release(queue2);
Related
Im trying to convert the following to objective-c code.
This is the current thread I have in C and works fine
//calling EnrollThread method on a thread in C
pthread_t thread_id;
pthread_create( &thread_id, NULL, EnrollThread, pParams );
//What the EnrollThread method structure looks like in C
void* EnrollThread( void *arg )
What my method structure looks like now that I've changed it to objective-c
-(void)enrollThreadWithParams:(LPBIOPERPARAMS)params;
Now I'm not sure how to call this objective-c method with the pthread_create call.
I've tried something like this:
pthread_create( &thread_id, NULL, [refToSelf enrollThreadWithParams:pParams], pParams );
But I believe I have it wrong. Can anyone enlighten me on why this does not work and what it is I need to do to fix it so that I can create my thread in the background? My UI is getting locked until the method finishes what it's doing.
I was thinking of also using dispatch_sync but I haven't tried that.
In objective C you don't really use pthread_create, although you can still use it, but the thread entry point needs to be a C function, so I'm not sure if this would be the best approach.
There are many options, as you can read in the Threading and Concurrency documents.
performSelectorInBackground method of NSObject (and subclasses)
dispatch_async (not dispatch_sync as you mentioned)
NSOperation and NSOperationQueue
NSThread class
I would suggest giving it a shot to the first one, since it is the easiest, and very straightforward, also the second one is very easy because you don't have to create external objects, you just place inline the code to be executed in parallel.
The go to reference for concurrent programming is the Concurrency Programming Guide which walks you through dispatch queues (known as Grand Central Dispatch, GCD) and operation queues. Both are incredibly easy to use and offer their own respective advantages.
In their simplest forms, both of these are pretty easy to use. As others have pointed out, the process for creating a dispatch queue and then dispatching something to that queue is:
dispatch_queue_t queue = dispatch_queue_create("com.domain.app", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
// something to do in the background
});
The operation queue equivalent is:
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
// something to do in the background
}];
Personally, I prefer operation queues where:
I need controlled/limited concurrency (i.e. I'm going to dispatch a bunch of things to that queue and I want them to run concurrent with respect to not only the main queue, but also with respect to each other, but I don't want more than a few of those running simultaneously). A good example would be when doing concurrent network requests, where you want them running concurrently (because you get huge performance benefit) but you generally don't want more than four of them running at any given time). With an operation queue, one can specify maxConcurrentOperationCount whereas this tougher to do with GCD.
I need fine level of control over dependencies. For example, I'm going to start operations A, B, C, D, and E, but B is dependent on A (i.e. B shouldn't start before A finishes), D is dependent upon C, and E is dependent upon both B and D finishing.
I need to enjoy concurrency on tasks that, themselves, run asynchronously. Operations offer a fine degree of control over what determines when the operation is to be declared as isFinished with the use of NSOperation subclass that uses "concurrent operations". A common example is the network operation which, if you use the delegate-based implementation, runs asynchronously, but you still want to use operations to control the flow of one to the next. The very nice networking library, AFNetworking, for example, uses operations extensively, for this reason.
On the other hand, GCD is great for simple one-off asynchronous tasks (because you can avail yourself of built-in "global queues", freeing yourself from making your own queue), serial queues for synchronizing access to some shared resource, dispatch sources like timers, signaling between threads with semaphores, etc. GCD is generally where people get started with concurrent programming in Cocoa and Cocoa Touch.
Bottom line, I personally use operation queues for application-level asynchronous operations (network queues, image processing queues, etc.), where the degree of concurrency becomes and important issue). I tend to use GCD for lower-level stuff or quick and simple stuff. GCD (with dispatch_async) is a great place to start as you dip your toe into the ocean of concurrent programming, so go for it.
There are two things I'd encourage you to be aware of, regardless of which of these two technologies you use:
First, remember that (in iOS at least) you always want to do user interface tasks on the main queue. So the common patterns are:
dispatch_async(queue, ^{
// do something slow here
// when done, update the UI and model objects on the main queue
dispatch_async(dispatch_get_main_queue(), ^{
// UI and model updates can go here
});
});
or
[queue addOperationWithBlock:^{
// do something slow here
// when done, update the UI and model objects on the main queue
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// do UI and model updates here
}];
}];
The other important issue to consider is synchronization and "thread-safety". (See the Synchronization section of the Threading Programming Guide.) You want to make sure that you don't, for example, have the main thread populating some table view while, at the same time, some background queue is changing the data used by that table view at the same time. You want to make sure that while any given thread is using some model object or other shared resource, that another thread isn't mutating it, leaving it in some inconsistent state.
There's too much to cover in the world of concurrent programming. The WWDC videos (including 2011 and 2012) offer some great background on GCD and asynchronous programming patterns, so make sure you avail yourself of that great resource.
If you already have working code, there is no reason to abandon pthreads. You should be able to use it just fine.
If, however, you want an alternative, but you want to keep your existing pthread entry point, you can do this easily enough...
dispatch_queue_t queue = dispatch_queue_create("EnrollThread", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
EnrollThread(parms);
});
im pretty new in Obj-C, and im wondering how to execute two functions in exactly the same time(with an accuracy to 1ms) without waiting for return, on different theards.
Currently i tried with
#define kBgQueue1 dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
dispatch_sync(kBgQueue1, ^{
[self function1];
});
dispatch_sync(kBgQueue1, ^{
[self function2];
});
dispatch_get_global_queue() gives you a concurrent queue, which can execute
tasks in parallel. But you have to use
dispatch_async() to execute the blocks without waiting for them to complete.
Note however that Grand Central Dispatch makes no guarantee about the timing.
Also GCD uses a limited thread pool, so there is also no guarantee that
the blocks are executed "simultaneously".
If you need more control about the thread creation then you would have to use lower-level classes/functions
such as NSThread or pthread_create().
As #Volker already said in a comment, you don't have 100% control over the
timing on OS X or iOS.
For more information, see the "Concurrency Programming Guide".
I have an app with a thread created as
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
});
I suspend all other threads and resume execution of this thread.
And while this thread spinning in a semaphore_wait() function, pausing the application or adding some symbolic breakpoint immediately causes it to exit from this semaphore_wait() although it must not.
I don't know the reason. Could it be XCode(4.5) causing this behaviour?
If you have questions about how to do asynchronous development in Cocoa, I'd refer you to the following resources:
Concurrency Programming Guide
Grand Central Dispatch Reference
WWDC 2012 video Asynchronous Design Patterns with Blocks, GCD, and XPC
But, in short, we don't use semaphore_wait (or other functions in the same category). We definitely don't suspend threads or anything like that.
When we absolutely need semaphores to communicate between various background threads, we use dispatch_semaphore_create, dispatch_semaphore_wait, and dispatch_semaphore_signal (and I've never seen those exhibit the behavior you describe). For example, I'll create a semaphore, wait for it on a background thread, and signal it 60 seconds later, and this is unaffected by quickly pausing and resuming execution in the debugger:
// create a semaphore
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// wait for signal on background thread (but don't block main thread)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"Waiting ...");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(#"Waiting done.");
});
// after one minute signal the semaphore
double delayInSeconds = 60.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSLog(#"About to signal");
dispatch_semaphore_signal(semaphore);
NSLog(#"Signal sent");
});
This is a fairly impractical example, and a poor use of a semaphore, but it illustrates how you can use one.
But one should never perform any blocking operation on the main thread, much less try to suspend it. In fact, in iOS, if you block the main thread while the app is starting up for too long, the watchdog may kill your app.
And as you'll see when you go through the standard Cocoa asynchronous design patterns video and the Concurrency Programming Guide, you'll see that standard usage of dispatch queues and operation queues often obviates the need for semaphores altogether (though we occasionally use them).
So, if your question is really about semaphore_wait, perhaps someone else can help you. But if you have a question about the appropriate Cocoa asynchronous pattern, let us know what you're functionally trying to accomplish and we can point you in the right direction.
There are several technologies (dispatch queues, operation queues, threads, etc.) available to Cocoa developers, and each has its own merits that makes it well suited for one scenario or another. But we rarely need to resort to direct thread programming anymore and just don't find ourselves using semaphore_wait or attempting to suspend threads.
It seems that lldb has a problem with SIGSTOP message. Check the following lldb revision.
Revision 155560
Suspend program threads before sending the SIGSTOP & resuming, so other threads won't get into trouble while we are waiting for the SIGSTOP.
rdar://problem/11174834
https://llvm.org/viewvc/llvm-project?view=revision&sortby=log&sortdir=down&revision=155560
The problem arises when debugging a semaphore_wait() that's on the main thread, semaphore_wait() on background threads are immune to this lldb problem.
Also, dispatch_semaphore_wait() is immune to this problem because it uses dispatch_semaphore_wait_slow() which has the following;
case DISPATCH_TIME_FOREVER:
do {
kr = semaphore_wait(dsema->dsema_port);
} while (kr == KERN_ABORTED);
http://www.opensource.apple.com/source/libdispatch/libdispatch-84.5.3/src/semaphore.c
So, it resumes on waiting when semaphore_wait() returns with KERN_ABORTED.
Is it safe to add an NSOperationQueue to an NSOperation, and then add this operation to another NSOperationQueue?
Here is some code to visualize what I am trying to do.
NSOperationQueue *mainQueue = [NSOperationQueue alloc] init];
// Here I declare some NSBlockOperation's, i.e. parseOperation1-2-3
// and also another operation called zipOperation, which includes
// an NSOperationQueue itself. This queue takes the processed (parsed) files
// and write them to a single zip file. Each operation's job is to write the data
// stream and add it to the zip file. After all operations are done,
// it closes the zip.
[zipOperation addDependency:parseOperation1];
[zipOperation addDependency:parseOperation2];
[zipOperation addDependency:parseOperation3];
[mainQueue addOperation:parseOperation1];
[mainQueue addOperation:parseOperation2];
[mainQueue addOperation:parseOperation3];
[mainQueue addOperation:zipOperation];
I have used this approach and have it running in live code deployed on the App Store. I haven't experienced any issues during development or in the last 2 months since the code has been live.
In my case I had a high level series of operations, some of which contained a set of sub operations. Rather than expose the detail of each sub operation into the high level code, I created NSOperations which themselves contained NSOperationQueues and enqueued their own sub operations. The code I ended up with was much cleaner and easier to maintain.
I read extensively into NSOperation and have not seen any commentary that warns against this approach. I reviewed a lot of information online, the Apple documentation, and WWDC videos.
The only possible "drawback" might be the added complexity of understanding and implementing a Concurrent operation. Embedding an NSOperationQueue in an NSOperation means that operation becomes Concurrent.
So that's a 'YES' from me.
Additional details about concurrent operations:
An NSOperationQueue calls the start method on a normal (non-concurrent) NSOperation and expects the operation to be finished by the time the start call returns. For instance some piece of code you supplied to NSBlockOperation is complete at the end of the block.
If the work will not be finished by the time the start call returns then you configure the NSOperation as a Concurrent operation, so the NSOperationQueue knows that it has to wait until you tell it that the operation is finished at some later point in time.
For example, concurrent operations are often used to run asynchronous network calls; the start method only starts the network call, which then runs in the background, and calls back to the operation when its finished. You then change the isFinished property of the NSOperation to flag that the work is now complete.
So.... Normally when you add operations to an NSOperationQueue that queue runs those operations in the background. So if you put an NSOperationQueue inside an NSOperation then that operations work will be done in the background. Therefore the operation is concurrent and you need to flag when the internal NSOperationQueue has finished processing all it's operations.
Alternatively there are some methods on NSOperationQueue such as waitUntilAllOperationsAreFinished which could be used to ensure all the work was done before the start call returns, however these involve blocking threads and I avoided them, you may feel more comfortable with that approach, and making sure you don't have any side effects from blocking threads.
In my case I was already familiar with Concurrent operations so it was straightforward just to set it up as a Concurrent operation.
Some documentation about concurrent operations:
Concurrency Programming Guide: Configuring Operations for Concurrent Execution
In this example they are detaching a thread to perform work in the background, in our case we would be starting the NSOperationQueue here.
I have an NSManagedObjectContext declared like so:
- (NSManagedObjectContext *) backgroundMOC {
if (backgroundMOC != nil) {
return backgroundMOC;
}
backgroundMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
return backgroundMOC;
}
Notice that it is declared with a private queue concurrency type, so its tasks should be run on a background thread. I have the following code:
-(void)testThreading
{
/* ok */
[self.backgroundMOC performBlock:^{
assert(![NSThread isMainThread]);
}];
/* CRASH */
[self.backgroundMOC performBlockAndWait:^{
assert(![NSThread isMainThread]);
}];
}
Why does calling performBlockAndWait execute the task on the main thread rather than background thread?
Tossing in another answer, to try an explain why performBlockAndWait will always run in the calling thread.
performBlock is completely asynchronous. It will always enqueue the block onto the queue of the receiving MOC, and then return immediately. Thus,
[moc performBlock:^{
// Foo
}];
[moc performBlock:^{
// Bar
}];
will place two blocks on the queue for moc. They will always execute asynchronously. Some unknown thread will pull blocks off of the queue and execute them. In addition, those blocks are wrapped within their own autorelease pool, and also they will represent a complete Core Data user event (processPendingChanges).
performBlockAndWait does NOT use the internal queue. It is a synchronous operation that executes in the context of the calling thread. Of course, it will wait until the current operations on the queue have been executed, and then that block will execute in the calling thread. This is documented (and reasserted in several WWDC presentations).
Furthermore, performBockAndWait is re-entrant, so nested calls all happen right in that calling thread.
The Core Data engineers have been very clear that the actual thread in which a queue-based MOC operation runs is not important. It's the synchronization by using the performBlock* API that's key.
So, consider 'performBlock' as "This block is being placed on a queue, to be executed at some undetermined time, in some undetermined thread. The function will return to the caller as soon as it has been enqueued"
performBlockAndWait is "This block will be executed at some undetermined time, in this exact same thread. The function will return after this code has completely executed (which will occur after the current queue associated with this MOC has drained)."
EDIT
Are you sure of "performBlockAndWait does NOT use the internal queue"?
I think it does. The only difference is that performBlockAndWait will
wait until the block's completion. And what do you mean by calling
thread? In my understanding, [moc performBlockAndWait] and [moc
performBloc] both run on its private queue (background or main). The
important concept here is moc owns the queue, not the other way
around. Please correct me if I am wrong. – Philip007
It is unfortunate that I phrased the answer as I did, because, taken by itself, it is incorrect. However, in the context of the original question it is correct. Specifically, when calling performBlockAndWait on a private queue, the block will execute on the thread that called the function - it will not be put on the queue and executed on the "private thread."
Now, before I even get into the details, I want to stress that depending on internal workings of libraries is very dangerous. All you should really care about is that you can never expect a specific thread to execute a block, except anything tied to the main thread. Thus, expecting a performBlockAndWait to not execute on the main thread is not advised because it will execute on the thread that called it.
performBlockAndWait uses GCD, but it also has its own layer (e.g., to prevent deadlocks). If you look at the GCD code (which is open source), you can see how synchronous calls work - and in general they synchronize with the queue and invoke the block on the thread that called the function - unless the queue is the main queue or a global queue. Also, in the WWDC talks, the Core Data engineers stress the point that performBlockAndWait will run in the calling thread.
So, when I say it does not use the internal queue, that does not mean it does not use the data structures at all. It must synchronize the call with the blocks already on the queue, and those submitted in other threads and other asynchronous calls. However, when calling performBlockAndWait it does not put the block on the queue... instead it synchronizes access and runs the submitted block on the thread that called the function.
Now, SO is not a good forum for this, because it's a bit more complex than that, especially w.r.t the main queue, and GCD global queues - but the latter is not important for Core Data.
The main point is that when you call any performBlock* or GCD function, you should not expect it to run on any particular thread (except something tied to the main thread) because queues are not threads, and only the main queue will run blocks on a specific thread.
When calling the core data performBlockAndWait the block will execute in the calling thread (but will be appropriately synchronized with everything submitted to the queue).
I hope that makes sense, though it probably just caused more confusion.
EDIT
Furthermore, you can see the unspoken implications of this, in that the way in which performBlockAndWait provides re-entrant support breaks the FIFO ordering of blocks. As an example...
[context performBlockAndWait:^{
NSLog(#"One");
[context performBlock:^{
NSLog(#"Two");
}];
[context performBlockAndWait:^{
NSLog(#"Three");
}];
}];
Note that strict adherence to the FIFO guarantee of the queue would mean that the nested performBlockAndWait ("Three") would run after the asynchronous block ("Two") since it was submitted after the async block was submitted. However, that is not what happens, as it would be impossible... for the same reason a deadlock ensues with nested dispatch_sync calls. Just something to be aware of if using the synchronous version.
In general, avoid sync versions whenever possible because dispatch_sync can cause a deadlock, and any re-entrant version, like performBlockAndWait will have to make some "bad" decision to support it... like having sync versions "jump" the queue.
Why not? Grand Central Dispatch's block concurrency paradigm (which I assume MOC uses internally) is designed so that only the runtime and operating system need to worry about threads, not the developer (because the OS can do it better than you can do to having more detailed information). Too many people assume that queues are the same as threads. They are not.
Queued blocks are not required to run on any given thread (the exception being blocks in the main queue must execute on the main thread). So, in fact, sometimes sync (i.e. performBlockAndWait) queued blocks will run on the main thread if the runtime feels it would be more efficient than creating a thread for it. Since you are waiting for the result anyway, it wouldn't change the way your program functioned if the main thread were to hang for the duration of the operation.
This last part I am not sure if I remember correctly, but in the WWDC 2011 videos about GCD, I believe that it was mentioned that the runtime will make an effort to run on the main thread, if possible, for sync operations because it is more efficient. In the end though, I suppose the answer to "why" can only be answered by the people who designed the system.
I don't think that the MOC is obligated to use a background thread; it's just obligated to ensure that your code will not run into concurrency issues with the MOC if you use performBlock: or performBlockAndWait:. Since performBlockAndWait: is supposed to block the current thread, it seems reasonable to run that block on that thread.
The performBlockAndWait: call only makes sure that you execute the code in such a way that you don't introduce concurrency (i.e. on 2 threads performBlockAndWait: will not run at the same time, they will block each other).
The long and the short of it is that you can't depend on which thread a MOC operation runs on, well basically ever. I've learned the hard way that if you use GCD or just straight up threads, you always have to create local MOCs for each operation and then merge them to the master MOC.
There is a great library (MagicalRecord) that makes that process very simple.