56 strcpy (request->path, filepath);
57 request->string = search;
58 request->next = NULL;
59 if (crew->first == NULL) {
60 crew->first = request;
61 crew->last = request;
62 } else {
63 crew->last->next = request;
64 crew->last = request;
65 } 66
67 crew->work_count++;
68 status = pthread_cond_signal (&crew->go);
69 if (status != 0) {
70 free (crew->first);
71 crew->first = NULL;
72 crew->work_count = 0;
73 pthread_mutex_unlock (&crew->mutex);
74 return status;
75 }
76 while (crew->work_count > 0) {
77 status = pthread_cond_wait (&crew->done, &crew->mutex);
78 if (status != 0)
79 err_abort (status, "waiting for crew to finish");
80 }
81 status = pthread_mutex_unlock (&crew->mutex);
82 if (status != 0)
83 err_abort (status, "Unlock crew mutex");
84 return 0;
85 }
Part 5 shows the initial thread (main) for the little work crew sample.
10-13 The program requires three arguments — the program name, a string for which to search, and a path name. For example, "crew butenhof ~"
15-23 On a Solaris system, call thr_setconcurrency to ensure that at least one LWP (kernel execution context) is created for each crew member. The program will work without this call, but, on a uniprocessor, you would not see any concurrency. See Section 5.6.3 for more information on "many to few" scheduling models, and Section 10.1.3 for information on "set concurrency" functions.
24-30 Create a work crew, and assign to it the concurrent file search.
■ crew.c part 5 main
1 /*
2 * The main program to "drive" the crew...
3 */
4 int main (int argc, char *argv[])
5 {
6 crew_t my_crew;
7 char line[128], *next;
8 int status;
9
10 if (argc < 3) {
11 fprintf (stderr, "Usage: %s string path\n", argv[0]);
12 return -1;
13 }
14
15 #ifdef sun
16 /*
17 * On Solaris 2.5, threads are not timesliced. To ensure
18 * that our threads can run concurrently, we need to
19 * increase the concurrency level to CREW_SIZE.
20 */
21 DPRINTF (("Setting concurrency level to %d\n", CREW_SIZE));
22 thr_setconcurrency (CREW_SIZE);
23 #endif
24 status = crew_create (&my_crew, CREW_SIZE);
25 if (status != 0)
26 err_abort (status, "Create crew");
27
28 status = crew_start (&my_crew, argv[2], argv[l]);
29 if (status != 0)
30 err_abort (status, "Start crew");
31
32 return 0;
33 }
4.3 Client/Server
But the Judge said he never had summed up before;
So the Snark undertook it instead,
And summed it so well that it came to far more
Than the Witnesses ever had said!
In a client/server system, a "client" requests that a "server" perform some operation on a set of data (Figure 4.3). The server performs the operation independently — the client can either wait for the server or proceed in parallel and look for the result at a later time when the result is required. Although it is simplest to have the client wait for the server, that's rarely very useful — it certainly doesn't
FIGURE 4.3
provide a speed advantage to the client. On the other hand, it can be an easy way to manage synchronization for some common resource.