Section 7.2, by the way, shows the development of a more robust and general (and more complicated) "work queue manager" package. A "work crew" and a "work queue" are related in much the same way as "invariants" and "critical sections" — it depends on how you look at what's happening. A work
The following program, called crew.c, shows a simple work crew. Run the program with two arguments, a string, and a file path. The program will queue the file path to the work crew. A crew member will determine whether the file path is a file or a directory—if a file, it will search the file for the string; if a directory, it will use readdir_r
to find all directories and regular files within the directory, and queue each entry as new work. Each file containing the search string will be reported on stdout.
Part 1 shows the header files and definitions used by the program. 7 The symbol CREW_SIZE determines how many threads are created for each work crew.
13-17 Each item of work is described by a work_t structure. This structure has a pointer to the next work item (set to NULL to indicate the end of the List), a pointer to the file path described by the work item, and a pointer to the string for which the program is searching. As currently constructed, all work items point to the same search string.
23-27 Each member of a work crew has a worker_t structure. This structure contains the index of the crew member in the crew vector, the thread identifier of the crew member (thread), and a pointer to the crew_t structure (crew).
33-41 The crew_t structure describes the work crew state. It records the number of members in the work crew (crew_size) and an array of worker_t structures (crew). It also has a counter of how many work items remain to be processed (work_count) and a list of outstanding work items (first points to the earliest item, and last to the latest). Finally, it contains the various Pthreads synchronization objects: a mutex to control access, a condition variable (done) to wait for the work crew to finish a task, and a condition variable on which crew members wait to receive new work (go).
43-44 The allowed size of a file name and path name may vary depending on the file system to which the path leads. When a crew is started, the program calculates the allowable file name and path length for the specified file path by calling path-conf, and stores the values in path_max and name_max, respectively, for later use.
1 #include
2 #include
3 #include
4 #include
5 #include "errors.h"
6
7 #define CREW_SIZE 4
8
9 /*
/*
10 * Queued items of work for the crew. One is queued by
11 * crew_start, and each worker may queue additional items.
12 */
13 typedef struct work_tag {
14 struct work_tag *next; /* Next work item */
15 char *path; /* Directory or file */
16 char *string; /* Search string */
17
18
19 } work_t, *work_p;
/*
20 * One of these is initialized for each worker thread in the
21 * crew. It contains the "identity" of each worker.
22 */
23 typedef struct worker_tag {
24 int index; /* Thread's index */
25 pthread_t thread; /* Thread for stage */
26 struct crew_tag *crew; /* Pointer to crew */
27 } worker_t, *worker_p;
28
29 /*
30 * The external "handle' ' for a work crew. Contains the
31 * crew synchronization state and staging area.
32 */
33 typedef struct crew_tag {
34 int crew_size; /* Size of array */
35 worker_t crew[CREW_SIZE];/* Crew members */
36 long work_count; /* Count of work items */
37 work_t *first, *last; /* First & last work item */
38 pthread_mutex_t mutex; /* Mutex for crew data */