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 ', 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 ', 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!

Lewis Carroll, The Hunting of the Snark

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 Client/Server

provide a speed advantage to the client. On the other hand, it can be an easy way to manage synchronization for some common resource.

If a set of threads all need to read input from stdin, it might be confusing for them to each issue independent prompt-and-read operations. Imagine that two threads each writes its prompt using printf, and then each reads the response using gets — you would have no way of knowing to which thread you were responding. If one thread asks 'OK to send mail?' and the other asks 'OK to delete root directory?' you'd probably like to know which thread will receive your response. Of course there are ways to keep the prompt and response 'connected' without introducing a server thread; for example, by using the flockfile and funlockfile functions to lock both stdin and stdout around the prompt-and-read sequences, but a server thread is more interesting — and certainly more relevant to this section.

In the following program, server.c, each of four threads will repeatedly read, and then echo, input lines. When the program is run you should see the threads prompt in varying orders, and another thread may prompt before the echo. But you'll never see a prompt or an echo between the prompt and read performed by the 'prompt server.'

7-9 These symbols define the commands that can be sent to the 'prompt server.' It can be asked to read input, write output, or quit.

14-22 The request_t structure defines each request to the server. The outstanding requests are linked in a list using the next member. The operation member contains one of the request codes (read, write, or quit). The synchronous member is nonzero if the client wishes to wait for the operation to be completed (synchronous), or 0 if it does not wish to wait (asynchronous).

27-33 The tty_server_t structure provides the context for the server thread. It has the synchronization objects (mutex and request), a flag denoting whether the server is running, and a list of requests that have been made and not yet processed (first and last).

35-37 This program has a single server, and the control structure (tty_server) is statically

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату