If you find yourself thinking that someone shouldn't interrupt you because you have the conversation mutex locked, you've begun to develop an intuitive understanding of threaded programming. You can apply that understanding to help you design better threaded code with less effort. If something wouldn't make sense in real life, you probably shouldn't try it in a program either.
1.4 About the examples in this book
This book contains a number of examples. All are presented as complete programs, and they have been built and tested on Digital UNIX 4.0d and Solaris 2.5.
All of these programs do something, but many do not do anything of any particular importance. The purpose of the examples is to demonstrate thread management and synchronization techniques, which are mere overhead in most real programs. They would be less effective at revealing the details if that "overhead" was buried within large programs that "did something."
Within the book, examples are presented in sections, usually one function at a time. The source code is separated from the surrounding text by a header and trailer block which include the file name and, if the example comprises more than one section, a section number and the name of the function. Each line of the source code has a line number at the left margin. Major functional blocks of each section are described in specially formatted paragraphs preceding the source code. These paragraphs are marked by line numbers outside the left margin of
* It may also be a good time to take a break and read some healthy escapist fiction for a while.
the paragraph, denoting the line numbers in the source listing to which the paragraph refers. Here's an example: 1-2 These lines show the header files included in most of the examples. The
■ sample.c part 1 sampleinfo
1 #include
2 #include "errors.h"
I have written these examples to use error checking everywhere. That is, I check for errors on each function call. As long as you code carefully, this isn't necessary, and some experts recommend testing only for errors that can result from insufficient resources or other problems beyond your control. I disagree, unless of course you're the sort of programmer who never makes a mistake. Checking for errors is not that tedious, and may save you a lot of trouble during debugging.
You can build and run all of the examples for yourself—the source code is available online at CFLAGS=-pthread -stdl -wl
. On Solaris, they were built with CFLAGS=-D_REENTRANT -D_POSIX_C_ SOURCE=199506 -lpthread
. Some of the examples require interfaces that may not be in the Pthreads library on your system, for example, clock_gettime, which is part of the POSIX. lb realtime standard. The additional realtime library is specified by the RTFLAGS variable, which is defined as RTFLAGS=-lrt on Digital UNIX, and as RTFLAGS=-lposix4 on Solaris.
On Solaris 2.5 systems, several of the examples require calls to thr_setcon-currency to ensure proper operation. This function causes Solaris to provide the process with additional concurrency. In a few cases, the example will not operate at all without this call, and in other cases, the example would fail to demonstrate some behavior.
1.5 Asynchronous programming, by example
"In one moment I've seen what has hitherto been Enveloped in absolute mystery, And without extra charge I will give you at large A Lesson in Natural History."
This section demonstrates some basic asynchronous programming, using a simple program that does something vaguely useful, by pretending to be an alarm clock with a command interface for which you would not consider paying a dime in a store. But then, this book is about threads, not user interfaces, and the code that I need to show takes up quite enough space already.