Technote 1071Working with Multiprocessing Services |
CONTENTS
Overview
Related Materials Downloadables |
This Technote
discusses some techniques for use with Apple's
Multiprocessing Services Library. Methods for sharing
information between tasks are discussed and several
examples are provided that show how to implement
the techniques discussed.
This Technote is primarily directed at developers interested in using Apple's Multiprocessing Services routines. |
Preemptive TasksPreemptive tasks are single parameter routines that return a
result of
type Listing 1 shows a simple task that creates a SimpleText file containing 1000 lines of text containing the string "Hello World\n". In this task, a number of the "safe" file manager calls are used to create a file, open its data fork, and write a bunch of strings to the file. When called, this task will run in the background (during mouse clicks, menu selections, et cetera) until it completes. During that time, the application that created this task (and all other applications) will be free to perform any other processing operations it desires.
The single parameter passed to a task is provided by the caller
when the task is created using the
Of course, callers will want to know the result codes returned
by the tasks they create. To allow for this, Multiprocessing
Services provides a mechanism where the result code returned by
the task can be passed back to the caller. However, this cannot
be done directly as often the time required for a task to execute
cannot be determined beforehand. So, to allow Multiprocessing
Services to pass back the result returned by the task to its caller,
it is possible to designate a queue, by providing it as a parameter
to the
If a task notification queue is provided as a parameter to the
Task notification queues are necessary in some cases. For instance,
calling In general, |
Intertask CommunicationsMultiprocessing services provides a number of facilities that can be used for communication between tasks. These facilities and how they can be used are discussed in this section. Whenever possible, applications should use these methods for communication between tasks. Other methods, such as polling global variables, are inefficient and often lead to difficult-to-track-down bugs. The methods discussed in this section are fast, efficient, and they provide a well-defined set of operations for passing messages or communicating state information between tasks. QueuesQueues are first-in-first-out message buffers designed for passing 96-bit messages between tasks. Each message is formatted as a group of three 32-bit integers. The format of the data passed between tasks is entirely up to the programmer. Here, the only requirement is that all tasks accessing the same queue agree on the format of the data being stored in the queue. Inserting and extracting elements is an atomic operation - many tasks can try to extract the next message from a given queue, but only one will successfully obtain it. Listing 5 illustrates how a queue can be used to pass commands to a server task for background processing. Here, the server task extracts messages from a queue and then it performs processing operations based on a dispatching mechanism.
The server task shown in listing 5 assumes that messages placed in the queue have a particular format. Specifically, the first 32-bit integer is a command selector and the next two 32-bit integers are additional parameters that may or may not be used in command processing. As the server task assumes this will be the format for all messages placed in the queue, it is useful to have a single routine that formats queue entries according to this agreed upon format when sending messages to the server task. The routine shown in Listing 6 provides this mechanism.
Often it is best to "wrap" the routine used to place commands
in a server task's command queue in this manner rather than
calling Event GroupsEvent groups are the fastest method available for communications between tasks. An event group is a 32-bit integer. Each bit in that integer is used to represent an individual event. Event groups can be used as a mechanism for sending simple boolean messages to tasks. When used in this way, each bit in the event group represents a message. Unlike queues, where messages are received one at a time,
it is possible that several "event" messages may be received
simultaneously in one call to
As event groups are the fastest method for passing messages between tasks, their use should always be considered. If the messages your task is designed to handle do not need to be processed in any particular order, then event groups are probably the best method for sending commands to your task. On the other hand, if the commands you are sending to your task must be processed in a definite order (or you must send additional data along with the command), then you should use a queue to send commands to your task. |
Interrupt-Level CommunicationsOften it is desirable to communicate between code running at different execution levels. For example, an application may want to send information from its main thread to a task. This section discusses the issues involved in communications between different types of tasks and it provides an example illustrating how a preemptive task can send messages to an interrupt-level task. For the purposes of this discussion, we will define the following three task types and discuss methods that can be used to communicate between them:
Table 1 lists the various methods that can be used for communicating between tasks running at different execution levels. Perhaps the most complex of the types of communication that can be done here is sending a message from a preemptive task to a classic interrupt-level task. The other ones are straight forward, but, as this one is complex, a sample of how it can be done is provided in listing 8, listing 9, and listing 10. Table 1. Methods for communicating between different execution levels for Mac OS applications.
Example: sending a message to an interrupt taskIn this example, message records are kept in two queues: the unused
message buffers available are kept in a Multiprocessing
Services queue and the message buffers containing data to be read by
the interrupt task are stored in an O.S. Queue. Whenever the
preemptive task needs
to send a message to the interrupt routine, it can extract an
unused message
buffer from the Multiprocessing Services queue, copy some data to it,
and then place the buffer in the O.S. Queue. The current
implementation of
Multiprocessing Services does not allow preemptive tasks to call
The interrupt routine extracts messages from the O.S. Queue and once it has finished with a message, it places the message back into the Multiprocessing Services queue so it can be used again by the preemptive task. Listing 8 contains the steps needed to set up the structures and variables used in this example.
Once the necessary structures and variables have been set up,
sending
a message from a preemptive task to an interrupt task is simply a
matter
of obtaining a message buffer from the free message buffer queue,
copying some data to it, and then calling the
Inside of the interrupt routine, messages can be extracted from
the queue using the
|
Resource ManagementOftentimes when many preemptive tasks are engaged in a complex task, there must be a mechanism in place to ensure the number of tasks attempting to utilize a limited number of resources does not outnumber the actual number of resources available. For example, if we have ten tasks and two printers, and each one of those tasks must print from time to time, then a mechanism must be in place to ensure that no more than two tasks will be using the printers at any given time. SemaphoresSemaphores allow you to restrict access to resources in a way that ensures that only a certain number of tasks may access a particular resource at any given time. Critical regionsCritical regions are a special type of semaphore that allow you to restrict access to a particular resource (section of code) to a single execution thread. |
Tips & Tricks
|
Related MaterialsMultiprocessing SDK.Multiprocessing Services Online Documentation. |
|