Thanks to its BSD lineage, MacOS X has a preemptive thread mechanism that is robust and scalable. In this article, I provide an introduction to the two key thread solutions on MacOS X going forward. I'll begin with a look at POSIX threads, then focus on the Cocoa class
NSThread
. I'll demonstrate how to use these solutions to create and manage a thread task. And, of course, I'll compare these approaches, and review some key guidelines for designing a thread-safe task. I'm assuming a working knowledge of ANSI C and Objective-C.Climate For Mac Os C 10 9
Aug 27, 2012 To Create a new View Controller, go to File New File, and in the window that pops up, choose OS X Cocoa Objective-C class, and click Next. Name the class MasterViewController, and type NSViewController for “Subclass of”. Make sure that the option “With XIB for user Interface” is selected. In the final popup, click Create.
Challenges of Threading
Memory management is more difficult with threads. The main application process gets its allocated memory from the host system. It can even ask for more memory to cover its growing needs. A thread, however, gets its memory share from the main process itself. This means its stack frame is smaller than the process' frame. The thread must dispose of any objects created by its tasks. It must avoid data structures too large to fit in its stack frame. It must know how to react to low-memory signals and to VM paging.
Some threads could take advantage of garbage collection. But the collection service adds extra overhead to the thread. And it can slightly degrade thread performance.
Sometimes, threads use the same resource, which leads to coordination problems. One thread might change the data in a resource while others are trying to read it. If both actions happen at the same time, the result is data corruption.
A thread might dispose of a shared resource, but not inform its fellow threads. When the other threads try to use the resource, they will fail and crash with an
EXC_BAD_ACCESS
error. A thread might lock a resource for its use, but fail to clear the lock afterwards. This blocks other threads from using the resource, causing a deadlock.Finally, a thread might fail to terminate. Instead, it stays in the background, hogging resources and processor cycles as it runs. The result is a runaway thread. It can be terminated only with a forced quit or with a hard system restart.
Thread Solutions on OS X
MacOS X offers four ways to create a threaded task. One way is with a POSIX thread (Pthread) library. Another is the Cocoa class
NSThread
. Both solutions create threads that are preemptively scheduled and scalable to multiple processor cores.Threads can also be created using the Carbon library Multiprocessor Services. This library has its roots in the Macintosh clone years. It was designed to support the DayStar clones, which sport multiple PowerPC processors. It too creates preemptive and scalable threads. But these threads cannot interact with view widgets.
Finally, threads can be created with the Carbon Thread Manager. This, however, creates threads that are scheduled cooperatively and are not scalable. Also, the last two options are deprecated on MacOS X 10.6 (Snow Leopard), and are likely obsolete on 10.7 (Lion) and later. So, I will focus exclusively on the first two approaches.
Threads with POSIX
The POSIX thread library provides methods and data types for creating and managing a pre-emptive thread. It is a standardized library, its behavior defined by the IEEE document 1003-1c-1995. It is platform-agnostic, and available on all POSIX-compliant systems such as Linux, BSD, and MacOS X. The library is also available on the Windows platform through third-party sources.
There are about 100 methods and data types in the current library. All their names have the prefix
pthread_
. Many methods fall in one of three categories:- Methods for managing a threaded task. Some create and start a thread, then dispose of it afterwards. Some collect the threads into a pool. Others alter the priority levels of each thread.
- Methods ands unique ID.The primary difference between the two methods is that
pthread_cancel()
can kill a designated thread, whereaspthread_exit()
kills only the current thread.Listing One implements a simple POSIX thread. The routineDoTask
is cast as generic pointer (line 19).Listing One: Implementing a POSIX thread
DoTask
takes a single input argumentanArg
, which is a pointer to an integer. The routine dereferences the argument and retrieves the integer value (line 24). It then outputs the value withprintf()
and proceeds with the rest of the task code (not shown).