37 err_abort (status, "Lock pipe mutex");
38 if (pipe->active <= 0)
39 empty = 1;
40 else
41 pipe->active--;
42
43 status = pthread_mutex_unlock (&pipe->mutex);
44 if (status != 0)
45 err_abort (status, "Unlock pipe mutex");
46 if (empty)
47 return 0;
48
49 pthread_mutex_lock (&tail->mutex);
50 while (!tail->data_ready)
51 pthread_cond_wait (&tail->avail, &tail->mutex);
52 *result = tail->data;
53 tail->data_ready = 0;
54 pthread_cond_signal (&tail->ready);
55 pthread_mutex_unlock (&tail->mutex);
56 return 1;
57 }
Part 6 shows the main program that drives the pipeline. It creates a pipeline, and then loops reading lines from stdin. If the line is a single "=" character, it pulls a result from the pipeline and prints it. Otherwise, it converts the line to an integer value, which it feeds into the pipeline.
■ pipe.c part 6 main
1 /*
2 * The main program to "drive" the pipeline...
3 */
4 int main (int argc, char *argv[])
5 {
6 pipe_t my_pipe;
7 long value, result;
8 int status;
9 char line[128];
10
11 pipe_create (&my_pipe, 10);
12 printf ("Enter integer values, or \"=\" for next result\n");
13
14 while (1) {
15 printf ("Data> ");
16 if (fgets (line, sizeof (line), stdin) == NULL) exit (0);
17 if (strlen (line) <= 1) continue;
18 if (strlen (line) <= 2 && line[0] == '=') {
19 if (pipe_result (&my_pipe, &result))
20 printf ("Result is %ld\n", result);
21 else
22 printf ("Pipe is empty\n");
23 } else {
24 if (sscanf (line, "%ld", &value) < 1)
25 fprintf (stderr, "Enter an integer value\n");
26 else
27 pipe_start (&my_pipe, value);
28 }
29 }
30 }
4.2 Work crew
The twelve jurors were all writing very busily on slates. "What are they doing?"Alice whispered to the Gryphon.
"They ca'n't have anything to put down yet, before the trial's begun." "They're putting down their names," the Gryphon whispered in reply, "for fear they should forget them before the end of the trial."
In a work crew, data is processed independently by a set of threads (Figure 4.2). A "parallel decomposition" of a loop generally falls into this category. A set of threads may be created, for example, each directed to process some set of rows or columns of an array. A single set of data is split between the threads, and the result is a single (filtered) set of data. Because all the threads in the work crew, in this model, are performing the same operation on different data, it is often known as SIMD parallel processing, for "single instruction, multiple data." The original use of SIMD was in an entirely different form of parallelism, and doesn't literally apply to threads — but the concept is similar.
FIGURE 4.2
The threads in a work crew don't have to use a SIMD model, though. They may perform entirely different operations on different data. The members of our work crew, for example, each remove work requests from a shared queue, and do whatever is required by that request. Each queued request packet could describe a variety of operations—but the common queue and "mission statement" (to process that queue) make them a "crew" rather than independent worker threads. This model can be compared to the original definition of MIMD parallel processing, "multiple instruction, multiple data."