title
brancg
adam_ev
oped resources forums contacts subscribe site_map home
 

forums


OpEd

All Mac Considered
Amen Corner
Apple Peel
Digital Canvas
Editorials
Ether Nectar
iMaculate
   Conception

Infinite Loop
Notes from Dis
Scientia et
   Macintosh

Skewed Mac
Treo of Life

Resources

Books
Contacts/Mission
Forums
Links
Reviews
Subscribe


RadTech

Applelust is looking to add writers to its staff. If you are interested or want to be part of the Applelust community, drop us a line with your resume or vita. We are always on the look out for good, very smart, and reliable people to join the staff. If you think you have what it takes, let us know.

- The Publisher

OS X World
Programming for OS X: Multithreading and When to Use It

©6-18-01 Mike Vannorsdel

One of the great features of Mac OS X is its pre-emptive multithreading. This allows the operating system to carry on multiple processes simultaneously. Indeed a powerful ability, but it must be used with care.

The idea behind multithreading is to split a process into many separate pieces so that the operating system has more options with distributing CPU cycles. In Mac OS X, each process or application has at least one thread, called the main thread. Some applications will have more than one thread, thus being a multithreaded application. More threads give the operating system more options on how it will compute data. It can let some threads receive more CPU time than others, off load threads to additional processors, or abort a thread's execution.

A thread can be thought of as a list of instructions. These lists are ultimately sent to the processor(s) where the instructions will be carried out. With multiple processes running, and some with multiple threads, there are quite a few lists of instructions that need to be done. The operating system is responsible for sorting these lists as to which ones need to be done more than others. More important lists will be allowed to use the processor longer than others. The operating system will send the first list to the processor for completion. Depending on the list's priority given by the operating system, the current list may be stopped by the operating system to allow for another list to get processor time. This is known as thread switching. Many times a second the operating system will switch which thread is active and using the processor. More important threads will average more time using the CPU. When there are multiple processors available, each processor may be working on a separate thread at any one time. But never on the same thread simultaneously. This effectively gets twice the work done (well almost).

Both Carbon and Cocoa applications can be multithreaded. Carbon will use Multiprocessing Services (as in Mac OS 9) and Cocoa uses the NSThread class. Breaking off a new thread in Cocoa is quite easy. Simply use NSThread's detachNewThreadSelector:toTarget:withObject: method. An example would be:

[NSThread detachNewThreadSelector:@selector(myFunction:) toTarget:self withObject:someObject];

This will detach the function myFunction in a new thread and pass it someObject. The new thread is now independent from the main thread. This means there's no guarantee that one will finish before the other. When you're going to break off a new thread, ideally the thread's work is independent and separate from the other threads.

There are two common reasons for using multiple threads.

1) You want the work to be done apart from the interface.

2) You want to use the advantages of multiple processors.

The first reason would be used when you don't want the interface busy while the application is working. Doing lengthy work in the main thread (which is also doing the interface's work) will cause the interface to be unusable until the work has finished. Doing the work in a separate thread will allow the main thread to be free for other work. The second reason would be used so that you can have multiple pieces of work being done simultaneously.

However, multithreading has its limits and there are some things you should think about before using it. There is some overhead involved in an application going from single threaded to multithreaded. There's also a little overhead involved in creating each additional thread. So only detach threads when there's enough work to make it worth the overhead.

Another problem has to do with classes that are not thread-safe. These are classes that shouldn't be used in threads other than the main thread. This is because they may give unexpected behavior or just not work at all. As a rule of thumb, the App Kit classes are not thread-safe, while the Foundation are. But there are exceptions for each, read the class documentation to be sure. This basically means you shouldn't interact with the interface from any thread other than the main thread. Though this may appear to work if you try it, you'll find you have memory leaking or sporadic results.

This brings me another thing you should know about using multithreading with Cocoa. When you detach a new thread, you need to create an auto-release pool for that thread. If you don't, auto-released objects will never be release (because there's no pool to release it), and thus a memory leak. The main thread is automatically given one so you never had to worry about that. But threads detached by you need you to add one. This is actually quite easy. Using the example above, myFunction would look like this:

- (void)myFunction:(id)someObject

{

NSAutoreleasePool * localPool = [[NSAutoreleasePool alloc] init];

...

//your code here

...

[localPool release];

}

The first line of the function creates a local auto-release pool for the auto-released objects to go. The last line releases the pool which in turn released its auto-released objects.

Cocoa does offer inter-thread communications via Distributed Objects. You can also throttle the threads if one requires the other to be at a certain point before continuing by using condition locks (NSConditionLock). But if you find yourself using a lot of condition locks or passing many objects and messages between threads, you may want to rethink using multiple threads.

Use multithreading with care or your application's performance will deeply suffer. This is the exact opposite of its usefulness! So don't get carried away and you'll produce a great programs that take advantage of this technology.

Mike Vannorsdel

Mike is the creator of "firewalk X," a firewall for OS X, and "Univert," and conversion utility for So X. And who knows, maybe more apps are on the way! ; )



©2000-2001 Applelust.com. All rights reserved. No part of this publication may be reproduced in any way without prior, expressed permission from the Publisher. It is the sole property of Applelust.com and its writers, who retain copyright to their own works. If you wish to link to us, please see our Privacy Statement for conditions. Apple, Macintosh, and Mac are trademarks of Apple Computer, Inc, with whom we are in no way affiliated or endorsed.

Hosting provided by itsamac.com -- Macintosh Powered Web Hosting

Serve Different

dreamy