Книга: Programming with POSIX® Threads
1.5.3 A version using multiple threads
1.5.3 A version using multiple threads
Now, let us try another alarm program, alarm_thread.c. It is much like the fork version in alarm_fork.c, except that it uses threads instead of child processes to create asynchronous alarms. Four Pthreads calls are used in this program:
• pthread_create creates a thread running the routine specified in the third argument (alarm_thread), returning an identifier for the new thread to the variable referenced by thread.
• pthread_detach allows Pthreads to reclaim the thread's resources as soon as it terminates.
• pthread_exit terminates the calling thread.
• pthread_self returns the calling thread's identifier.
4-7 The alarm_t structure defines the information stored for each alarm command, the number of seconds until the alarm is due, and the message string that will be printed by the thread.
? alarm_thread.c part 1 definitions
1 #include <pthread.h>
2 #include "errors.h" 3
4 typedef struct alarm_tag {
5 int seconds;
6 char message[64];
7 } alarm_t;
1-8 The alarm_thread function is the "alarm thread." That is, each alarm thread is created running this function, and when the function returns the thread terminates. The function's argument (void *arg) is the fourth argument that was passed to pthread_create, in this case, a pointer to the control packet (alarm_t) created for the alarm request that the thread is to satisfy. The thread starts by "mapping" the void * argument as a pointer to a control packet. The thread detaches itself by calling pthread_detach, which informs Pthreads that the application does not need to know when the thread terminates or its termination status.
9-12 The thread sleeps for the number of seconds specified in its control packet, and then prints the message string. Finally, the thread frees the control packet and returns. When a thread returns from its initial routine, as it does here, the thread terminates. Normally, Pthreads would hold the thread's resources so that another thread could later determine that it had exited and retrieve a final result. Because the thread detached itself, none of that is necessary.
? alarm_thread.c part 2 alarm_thread
1 void *alarm_thread (void *arg)
2 {
3 alarm_t *alarm = (alarm_t*)arg;
4 int status;
5
6 status = pthread_detach (pthread_self ());
7 if (status != 0)
8 err_abort (status, "Detach thread");
9 sleep (alarm->seconds);
10 printf ("(%d) %sn", alarm->seconds, alarm->message);
11 free (alarm);
12 return NULL;
13 }
The main program of alarm_thread.c is much the same as the other two variants. It loops, reading and interpreting command lines as long as it can read from stdin.
12-25 In this variation, main allocates heap storage (alarm_t) for each alarm command. The alarm time and message are stored in this structure, so each thread can be given the appropriate information. If the sscanf call fails to "parse" a correct command, the heap storage is freed.
26-29 An alarm thread is created, running function alarm_thread, with the alarm data (alarm_t) as the thread's argument.
? alarm_thread.c_ part 3 main
1 int main (int argc, char *argv[])
2 {
3 int status;
4 char line[128];
5 alarm_t *alarm;
6 pthread_t thread;
7
8 while (1) {
9 printf ("Alarm> ");
10 if (fgets (line, sizeof (line), stdin) == NULL) exit (0);
11 if (strlen (line) <= 1) continue;
12 alarm = (alarm_t*)malloc (sizeof (alarm_t));
13 if (alarm == NULL)
14 errno_abort ("Allocate alarm");
15
16 /*
17 * Parse input line into seconds (%d) and a message
18 * (%64[^n]), consisting of up to 64 characters
19 * separated from the seconds by whitespace.
20 */
21 if (sscanf (line, "%d %64[^nJ",
22 &alarm->seconds, alarm->message) < 2) {
23 fprintf (stderr, "Bad commandn");
24 free (alarm);
25 } else {
2 6 status = pthread_create (
27 &thread, NULL, alarm_thread, alarm);
28 if (status != 0)
29 err_abort (status, "Create alarm thread");
30 }
31 }
32 }
- 1.5.2 A version using multiple processes
- 1.5 Asynchronous programming, by example
- 1.5.1 The baseline, synchronous version
- ODS version
- Caveats using NAT
- Using Double Quotes to Resolve Variables in Strings with Embedded Spaces
- Type Conversion
- Data Binding Using the GridView Control
- Using the kill Command to Control Processes
- 4 A few ways to use threads
- Installing Using a Network
- Using X