1.9.2 Types and interfaces
This section briefly outlines the Pthreads data types, and some of the rules for interpreting them. For a full description of the "object" represented by each type and how to create and use those objects in a program, see the appropriate sections later in this book, as shown in Table 1.2.
Type | Section | Description |
pthread_t | 2 | thread identifier |
pthread_mutex_t | 3.2 | mutex |
pthread_cond_t | 3.3 | condition variable |
pthread_key_t | "access key" for thread-specific data | |
pthread_attr_t | 5.2.3 | thread attributes object |
pthread_mutexattr_t | 5.2.1 | mutex attributes object |
pthread_condattr_t | 5.2.2 | condition variable attributes object |
pthread_once_t | "one time initialization" control context |
TABLE 1.2
AII Pthreads types are "opaque." Portable code cannot make assumptions regarding the representation of these types.
All of the "pthread" types listed in Table 1.2 are considered
1.9.3 Checking for errors
Pthreads introduces a new way to report errors,without using the errno
variable.
The Pthreads amendment is the first part of POSIX to depart from the ancient UNIX and C language conventions regarding error status. Traditionally, functions that succeed returned a useful value if appropriate, or otherwise indicated success by returning the value 0. On failure, they returned the special value -1, and set the global value errno
to a code specifying the type of error.
The old mechanism has a number of problems, including the fact that it is difficult to create a function that can both report an error errno
was an extern int variable. Since such a variable can have only one value at a time, it can support only a single stream of execution within the process.
Pthreads functions don't set errno
on errors! (But most other POSIX functions do.)
New functions in the Pthreads standard reserve the return value for error status, and errno
is not used. Pthreads functions return the value 0 on success, and include an extra output parameter to specify an address where "useful results" are stored. When a function cannot complete successfully, an error code from the
Pthreads also provides a per-thread errno
, which supports other code that uses errno
. This means that when one thread calls some function that reports an error using errno
, the value cannot be overwritten, or read, by any other thread— you may go on using errno
just as you always have. But if you're designing new interfaces you should consider following the new Pthreads convention for reporting errors. Setting or reading the per-thread errno
involves more overhead than reading or writing a memory location, or returning a value from a function.
To wait for a thread, for example, and check for an error, you might use code like that shown in the following code example, thread_error.c. The pthread_join
function, used to wait for a thread to terminate, will report an invalid thread identifier by returning the error code ESRCH. An uninitialized pthread_t
is likely to be an invalid thread identifier on most implementations. The result of running this program should be a message such as "error 3: no such process."
In the unlikely event that the uninitialized thread variable has a pthread_t
value that is not invalid, it should be the ID of the initial thread (there are no other threads in this process). In this case, pthread_join
should either fail with EDEADLK, if your implementation of Pthreads detects self-deadlock, or the thread will hang waiting for itself to exit.
■ thread_error.c
1 #include
2 #include
3 #include
5 int main (int argc, char *argv[])
6 {
7 pthread_t thread;
8 int status;
9
10 /*