18-25 The program creates a thread by calling pthread_create, and then waits for it by calling pthread_join. You don't need to wait for a thread, but if you don't, you'll need to do something else to make sure the process runs until the thread completes. Returning from main will cause the process to terminate, along with all threads. You could, for example, code the main thread to terminate by calling pthread_exit, which would allow the process to continue until all threads have terminated.
26-29 When the join completes, the program checks the thread's return value, to be sure that the thread returned the value it was given. The program exits with 0 (success) if the value is NULL, or with 1 otherwise.
It is a good idea for all thread functions to return something, even if it is simply NULL. If you omit the return statement, pthread_join will still return some value—whatever happens to be in the place where the thread's start function would have stored a return value (probably a register).
■ lifecycle.c
1 #include
2 #include "errors.h" 3
4 /*
5 * Thread start routine.
6 */
7 void *thread_routine (void *arg)
8 {
9 return arg; 10 }
11
12 main (int argc, char *argv[])
13 {
14 pthread_t thread_id;
15 void *thread result;
16 int status;
17
18 status = pthread_create (
19 &thread_id, NULL, thread_routine, NULL);
20 if (status != 0)
21 err_abort (status, "Create thread");
22
23 status = pthread_join (thread_id, &thread_result);
24 if (status != 0)
25 err_abort (status, "Join thread");
26 if (thread_result == NULL)
27 return 0;
28 else
29 return 1;
30 }
If the "joining" thread doesn't care about the return value, or if it knows that the "joinee" (the thread with which it is joining) didn't return a value, then it can pass NULL instead of &retval in the call to pthread_join
. The joinee's return value will be ignored.
When the call to pthread_join
returns, the joinee has been pthread_join
. The terminating thread would store its return value (or any other information) in some known location, and broadcast the condition variable to wake all threads that might be interested.
2.2 The life of a thread
Come, listen, my men, while I tell you again
The five unmistakable marks
By which you may know, wheresoever you go.
The warranted genuine Snarks.
At any instant, a thread is in one of the four basic states described in Table 2.1. In implementations, you may see additional "states" that distinguish between various reasons for entering the four basic states. Digital UNIX, for example, represents these finer distinctions as "substates," of which each state may have several. Whether they're called "substates" or additional states, "terminated" might be divided into "exited" and "cancelled"; "blocked" might be broken up into "blocked on condition variable," "blocked on mutex," "blocked in read," and so forth.