Creating exactly N threads with Grand Central Dispatch (GCD) - iphone

I know that i can execute tasks asynchronously with dispatch_async and dispatch_get_global_queue.
But how many threads dispatch_async create?
What should i do to execute exactly N (no more, no less) threads with GCD, and performe some tasks on them? After execution of task i need to add new task in released thread, maybe in complitation block of previous task.
Or maybe i can control the count of threds with NSOperationQueue?
I know that it has property maxConcurrentOperationCount, but it control only maximum limit of tasks. So, Can I be sure that NSOperationQueue creates no less than 8 threads, in case when i set maxConcurrentOperationCount = 8 and add 12 operations to the NSOperationQueue?
Thank you very much!

You should look into NSThread. It's the way to go if you need fine grain control over exactly the number of threads you want to have running.

Subclass NSOperation for the tasks you want to do and put them into an NSOperationQueue. You can set the number of concurrent operations on the queue.
NSOperationQueue *q = [[NSOperationQueue alloc] init];
q. maxConcurrentOperationCount = N;

Queue concept is different from thread. Go through NSThread class. Since NSOperation uses GCD you can't set thread from here. You can merge the NSThread and NSOperation creating and passing different threads. But why would you do that? more thread doesn't mean more speed, usually is the opposite with a lot of concern about memory, locking, concurrency etc.
You should have a very specific reason.

If you want to control the max count of threads when using gcd, you can make use of DispatchSemaphore. Firstly, create a semaphore with the max count, secondly at the beginning of a task, semaphore.wait(), finally at the end of a task, semaphore.signal().

Related

Running parallel tasks in background

I am using NSOperationQueue to run the task. I am using background processing in my application. But while adding tasks in NSOperationQueue, I found that tasks will be added in a queue format.
Does NSOperationQueue performs parallel task or sequential task processing?
If not parallel, then how can I achieve parallel task operations in my app?
I would recommend you read this document about concurrency programming.
You can perform parallel tasks by using "performSelectorInBackground" method. In this you are just showing the foreground tasks, meanwhile background tasks is being in progress. I have already answered on the following link, please follow the link given below with accepted answer. Perhaps it will help you.
http://[stackoverflow.com/questions/8725636/cant-get-the-activity-indicator-to-show-on-iphone-app/8725875#8725875][1]
Thanks!
Regards!
Khalid Usman
Use the setMaxConcurrentOperationCount: to set the number of concurrent operations.
I would suggest that you read this. The relevant information for you is:
Operation queues work with the system to restrict the number of concurrent operations to a value that is appropriate for the available cores and system load.
Although the NSOperationQueue class is designed for the concurrent execution of operations, it is possible to force a single queue to run only one operation at a time. The setMaxConcurrentOperationCount: method lets you configure the maximum number of concurrent operations for an operation queue object. Passing a value of 1 to this method causes the queue to execute only one operation at a time. Although only one operation at a time may execute, the order of execution is still based on other factors, such as the readiness of each operation and its assigned priority.

Implement a mechanism for chaining messages in Objective-C?

I'm writing an app which requires running a method after another method completes. (Common scenario, right?)
I'm trying to implement chained methods. The best I've come up with is to call performSelector:withObject:afterDelay:. I'm simply not sure if that is the best way to do this. I've looked into how the Cocos2d game engine implements its CCSequence class, but I'm not sure I understand it.
I suspect blocks would do well here, except I'm not sure how to use them as callback objects or whatever.
How would I implement a mechanism for running methods, one after the other? (I'm open to using timers or blocks, but I don't know how I'd use blocks in this case.)
Edit:
To clarify, I'm trying to implement a system like cocos2d's CCSequence class, which takes a few methods and "dispatches" them in sequence. Things like animations, which take much more than a single clock cycle to run.
I'm not looking to block the main thread, nor do I want to hard code methods to each other. Cocos2d has a sequencing system where I can pass in methods to a queue and run them sequentially.
Edit 2:
Also, I'd like to be able to cancel my scheduled queues, and so I'm not sure GCD is a good match for this. Can GCD serial queues be canceled?
You can use the technique of Thread Migration
Then here comes the interesting task called GCD-Grand Central Dispatch
Grand Central Dispatch (GCD) is a technology developed by Apple Inc.
to optimize application support for systems with multi-core processors
and other symmetric multiprocessing systems.It is an implementation of
task parallelism based on the thread pool pattern.
GCD works by allowing specific tasks in a program that can be run in
parallel to be queued up for execution and, depending on availability
of processing resources, scheduling them to execute on any of the
available processor cores
Dispatch Queues are objects that maintain a queue of tasks, either anonymous code blocks or functions, and execute these tasks in their
turn. The library automatically creates several queues with different
priority levels that execute several tasks concurrently, selecting the
optimal number of tasks to run based on the operating environment. A
client to the library may also create any number of serial queues,
which execute tasks in the order they are submitted, one at a time.
Because a serial queue can only run one task at a time, each task
submitted to the queue is critical with regard to the other tasks on
the queue, and thus a serial queue can be used instead of a lock on a
contended resource.
Dispatch queues execute their tasks concurrently with respect to other
dispatch queues. The serialization of tasks is limited to the tasks in
a single dispatch queue.
In your case you can use Serial Dispatch Queues
Serial queues are useful when you want your tasks to execute in a
specific order. A serial queue executes only one task at a time and
always pulls tasks from the head of the queue. You might use a serial
queue instead of a lock to protect a shared resource or mutable data
structure. Unlike a lock, a serial queue ensures that tasks are
executed in a predictable order. And as long as you submit your tasks
to a serial queue asynchronously, the queue can never deadlock.
Unlike concurrent queues, which are created for you, you must
explicitly create and manage any serial queues you want to use. You
can create any number of serial queues for your application but should
avoid creating large numbers of serial queues solely as a means to
execute as many tasks simultaneously as you can. If you want to
execute large numbers of tasks concurrently, submit them to one of the
global concurrent queues. When creating serial queues, try to identify
a purpose for each queue, such as protecting a resource or
synchronizing some key behavior of your application.
dispatch_queue_t queue;
queue = dispatch_queue_create("com.example.MyQueue", NULL);
this code shows the steps required to create a custom serial queue.
The dispatch_queue_create function takes two parameters: the queue
name and a set of queue attributes. The debugger and performance tools
display the queue name to help you track how your tasks are being
executed. The queue attributes are reserved for future use and should
be NULL.
Grand Central Dispatch provides functions to let you access several
common dispatch queues from your application:
Use the dispatch_get_current_queue function for debugging purposes
or to test the identity of the current queue. Calling this function
from inside a block object returns the queue to which the block was
submitted (and on which it is now presumably running). Calling this
function from outside of a block returns the default concurrent queue
for your application.
Use the dispatch_get_main_queue function to get the serial
dispatch queue associated with your application’s main thread. This
queue is created automatically for Cocoa applications and for
applications that either call the dispatch_main function or configure
a run loop (using either the CFRunLoopRef type or an NSRunLoop object)
on the main thread.
Use the dispatch_get_global_queue function to get any of the
shared concurrent queues.
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.
Source: Concurrency Programming Guide
What about using a serial GCD queue?
private dispatch queues
Serial queues (also known as private dispatch queues) execute one task at a time in the order in which they are added to the queue. The currently executing task runs on a distinct thread (which can vary from task to task) that is managed by the dispatch queue. Serial queues are often used to synchronize access to a specific resource.
You can create as many serial queues as you need, and each queue operates concurrently with respect to all other queues. In other words, if you create four serial queues, each queue executes only one task at a time but up to four tasks could still execute concurrently, one from each queue. For information on how to create serial queues, see “Creating Serial Dispatch Queues.”
(source)
This would be useful if you want that all of your messages be handled in a background thread.
There are two performSelector method that can wait for completion, no need to guess a timing.
[self performSelector:<#(SEL)#> onThread:<#(NSThread *)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];
[self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];
It sounds like you want to check out NSOperationQueue, NSOperation, and either NSBlockOperation or NSInvocationOperation. Unlike a GCD queue, an NSOperationQueue supports cancelling jobs.
You can create your own queue and set its maximum concurrent operation count to 1 to force it to execute operations serially. Or you can set dependencies between operations to force those operations to run serially.
Start with the chapter on Operation Queues in the Concurrency Programming Guide.
I finally found what I'm looking for. Completion blocks. Simply put, I'd write a method like this:
- (void) performSomeActionWithCompletion:(void (^)()) completion{
[self someAction];
if(completion()){
completion();
}
}
Now I can call my method like so:
[self performSomeActionWithCompletion:^{
NSLog(#"All done! (Well, not the async stuff, but at any rate...)");
}];

NSRunLoops in Cocoa?

Let's say I have 2 threads, one is the main thread and another one, a secondary thread. The main thread is being used the most, but sometimes (rarely) I want the secondary thread to do some work based on calls from the main thread. Most of the time the secondary thread should sleep. Now after some searching I understand the way to do this is to use runLoops. So I tried to read apple's docs (http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html#//apple_ref/doc/uid/10000057i-CH16-SW5)
but it looks to me very complex and I'm having some hard time there. Is there an elegant and simple way to achieve what I described? Any similar runLoop code examples out there that I can run and play with?
Thanks
Each thread has a run loop.
Each run loop has a list of things that need to be done. These things are said to be “scheduled” on the run loop, although not all of them are scheduled for a specific date and time:
Timers are.
Sources aren't. They generally wait for something to come knocking at a Mach kernel port or a file descriptor.
When the run loop is running, it's usually not running—that is, the thread is sleeping, not consuming any CPU cycles. (If you sample it, you'll find the process appearing to be stuck in mach_msg_trap. This is the “wait-for-something-to-happen” system call.) The kernel wakes up the thread (which thereby returns from mach_msg_trap) when something happens that the thread's run loop needs to take care of.
The way to do exactly what you described is to implement a run loop source. You schedule the source on the secondary thread's run loop, implement it by doing work, and signal it from the primary thread when there's work to be done.
However, NSOperation is almost certainly a better solution, as it's designed for the case you described: Discrete units of work that need to be done serially, up to N (which you choose and is at least 1) at a time.
Note that NSOperationQueue reuses threads, so it does not necessarily create a new thread for every operation. Indeed, not doing that is part of the point: It creates the threads lazily, and uses any that it already has that aren't doing anything.
This sounds like just the sort of thing NSOperation/NSOperationQueue was made for. If you only have the occasional "units of work", why not make them an operation, then monitor it for completion and update your UI accordingly?
Matt Gallagher has a nice blog article comparing the secondary thread approach with other ways of getting background work done.
http://cocoawithlove.com/2010/09/overhead-of-spawning-threads.html
In your case, you don't have to be concerned with thread-creation overhead. But Matt's code examples might provide some insight into managing the secondary thread's runloop.
All that said, I would go with Joshua's advice and just use an NSOperationQueue and an NSOperation to do the background work. If the work could be encapsulated in an NSInvocation, you can use an NSInvocationOperation and avoid an NSOperation subclass.

Problem about using NSOperationQueue and NSOperation in iphone OS

Im using NSOperation to do a task: download some files with NSURLConnection and then merge files that spend much cpu and memory
I need to excute the task in new/background thread
So I add some these tasks to NSOperationQueue and set maxConcurrentOperationCount = 2
But the result is when merging files it will block the main thread(UI not respond for a while)
,it seems not excuting in new/background thread
how to make it go as I expected ?
What type of operations are you putting in the NSOperationQueue? Apple's documentation for the NSOperationQueue includes this note:
Note: In iOS, operation queues do not
use Grand Central Dispatch to execute
operations. They create separate
threads for non-concurrent operations
and launch concurrent operations from
the current thread. For a discussion
of the difference between concurrent
and non-concurrent operations and how
they are executed, see NSOperation Class Reference.
Since you using NSOperationqueue,therefore you are having only two files at one time and you can merge only them because all the other threads or files are not present there.
So for merging them together you will have to keep them together at one time.

NSOperationQueue and concurrent vs non-concurrent

I want to setup a serialized task queue using NSOperationQueue but I'm a little confused by the terminology discussed in the documentation.
In the context of an NSOperation
object, the terms concurrent and
non-concurrent do not necessarily
refer to the side-by-side execution of
threads. Instead, a non-concurrent
operation is one that executes using
the environment that is provided for
it while a concurrent operation is
responsible for setting up its own
execution environment.
What does it mean to setup "own execution environment'?
My NSOperation derived tasks need to execute serially in the order they were added to the queue.
So I thought that this implies a 'non-concurrent' operation so I'd implement 'main' for the work that needs to be completed and also return NO for 'isConcurrent'. In addition, NSOperationQueue's 'setMaxConcurrentOperationCount' would be set to 1.
The reason I am not setting up NSOperation dependency between these tasks is because the order they're inserted into the queue is the order they should be completed.
Are these assumptions correct?
NSOperationQueue always executes operations concurrently, while taking dependencies into account.
A "non-concurrent" operation requires a separate thread in order to execute concurrently. NSOperationQueue is responsible for providing this thread. In other words, a non-concurrent operation depends on NSOperationQueue to make it a concurrent operation.
A "concurrent" operation is concurrent on its own; it doesn't need NSOperationQueue to create a thread for it. An example would be an operation that uses asynchronous file IO.
If you want two or more operations to execute serially you need to use dependencies.
If you want an operation to block the main thread then don't use NSOperationQueue; just run each operation one after the other on the main thread.
To manually set maximum of concurrent operations, use method on operationQueue setMaxConcurrentOperationCount:
Do you really need to subclass NSOperation? Why not just use NSInvocationOperation and its addDependency: method?
See my answer in this SO question.