Learn Objective-C on the Mac - Mark Dalrymple [157]
Figure 16-3. The final GUI touch-up
Now bring up the Attributes Inspector. Click to turn off both the Display When Stopped and Indeterminate checkboxes, then set its Minimum and Current values to 0, and its Maximum value to 4. Now switch to the Bindings Inspector, where you’ll configure two bindings. First, bind its Animate attribute to the app delegate’s isWorking key, just like you did for the circular progress indicator. Then, bind its Value attribute to the app delegate’s completed key.
Now save your work, Build & Run, and click the Start button. You should now see that beside the circular progress indicator, a horizontal progress indicator also appears, with a bar moving across as each of the work-methods completes.
And there you have it: relatively painless concurrency. Granted, this contrived example isn’t much compared to a large application, but these concepts can scale up to handle more complex situations as well. What we’ve shown you works well in today’s Leopard and iPhone applications, but Apple didn’t stop there. Starting with Snow Leopard, most of the design of NSOperation and NSOperationQueue has been reimplemented at a lower level in the OS, resulting in a nice piece of technology called Grand Central Dispatch.
GCD: Low-Level Queuing
This idea of putting units of work into queues that can be executed in the background, with the system managing the threads for you, is really powerful, and greatly simplifies many development situations where concurrency is needed. It seems that once this technology was up and running in the form of NSOperationQueue in Leopard, Apple decided to make a more general solution, that could work not only from Objective-C, but also C and C++. Starting with Snow Leopard, this solution, called Grand Central Dispatch (which we’ll call GCD from now on) is ready for use. GCD puts most of the core concepts of NSOperationQueue—units of work, painless background processing, automatic thread management—into a C interface that can be used from all of the C-based languages. This means that it’s not just for Cocoa programmers. Now even low-level command-line utilities written in C can take advantage of these features. NSOperationQueue itself was rewritten for Snow Leopard using GCD, and to top things off, Apple has made its implementation of GCD open-source, so that it could be ported to other Unix-like OSes as well.
The main difference between the design of NSOperationQueue and the queues in GCD is that while NSOperationQueue can deal with arbitrarily complex dependency relationships between its NSOperations to determine in what order they should be executed, the GCD queues are strictly FIFO (first-in, first-out). Units of work added to a GCD queue will always be started in the order they were placed in the queue. That being said, they may not always finish in the same order, because a GCD queue will automatically distribute its work among multiple threads.
Another important difference exists between the implementation of NSOperationQueue on Leopard and iPhone, and the implementation of GCD on Snow Leopard (which also defines the implementation of NSOperationQueue on Snow Leopard). In the older implementations, NSOperationQueue starts up a new thread for each operation when it’s about to run, and terminates the thread when it’s done. In the newer implementations, each queue has access to a pool of threads which are reused throughout the lifetime of the application. GCD will always try to maintain a pool of threads that’s appropriate for the machine’s architecture, automatically taking advantage of a more powerful machine by utilizing more processor cores when it has work to do.
Becoming a Blockhead
Along with GCD, Apple has released a bit of new syntax to the C language itself (and, by extension, Objective-C and C++), to implement a language feature