P.J. Plauger has been a prolific programmer, textbook author, and software entrepreneur. He is secretary of the ANSI C standards committee, X3J11, and convenor of the ISO C standards committee.
Introduction
Concurrent programming is hard. It's hard enough to do it UNIX style, where each concurrent entity is a separate program. (Rarely do you have a process fork unless the child process immediately execs another program.) It's really tough when you try for parallel operation within a single program (or function, or expression). Incorrect code can be too easy to write, correct code can be too hard to read.Committee X3J11 spent most of a year trying to clean up the semantics of Standard C for the parallel programmers. The notorious noalias type qualifier was designed explicitly to aid in the writing of functions that could be vectorized semiautomatically. It didn't stay in the language because we didn't have time to chase down all the implications of such a radically new concept. I like to think that the exercise was not a complete waste of time, even if it did delay the standard.
An easier way to parallelize C is to extend the language. (I mean extend it even more than adding the odd noalias declaration). Require the user to add hints in critical places where you think parallel operation can and should occur. That's what most of the successful concurrent FORTRAN implementations do. Most customers seem to find it a palatable approach.
One problem is to figure out what extensions to add. Commercial computers that support concurrent programs are far from identical. What works for one machine may be hard to port to another. Even worse, software mechanisms for describing concurrency are still evolving. Should you use locks, semaphores, monitors, or Ada-style rendezvous? Leave one out and someone will complain. Throw in too many and elegance goes out the window. There's no easy answer today.
With that in mind, let's look at three recent books on concurrent programming in C.
Programming Parallel Processes
Robert G. Babb II, Addison-Wesley, Reading MA, 1988.This book provides a comparison of eight commercial concurrent computers. Students from Babb's graduate seminar at the Oregon Graduate Center solved the same problem on each of the machines. About half the book is a report about each machine. The reports focus on the program development environment and the pitfalls encountered by a novice user. No attempt is made to develop credible performance comparisons. The last half of the book consists of appendixes listing the code for each machine plus any relevant documentation peculiar to that machine.
Most of these machines have C compilers. That's the good news. The bad news is that FORTRAN is still the language of choice for parallel programming. The language is more amenable to sorting out aliasing issues. It also has a longer history of being mucked over by the parallelizers. As a result, nearly all of the examples in this book are in FORTRAN. You will find just enough C to whet your interest, not enough to satisfy your curiosity.
If you want to get a feel for the current state of the art, you might want to read this book. It is more a collection of trip reports than a general overview of the field. That can be of use to programmers in the trenches, however. If you want to see how to do concurrent programming in C, you may be frustrated. You will have to intuit many of the lessons from FORTRAN.
The Concurrent C Programming Language
Narain Gehani and William D. Roome, Silicon Press, Summit NJ, 1989.Here is a serious attempt to introduce concurrency directly into C. The authors have altered Stroustrop's C++ to C translator, cfront, to accept a different dialect. That dialect has extensions that let you specify process creation, control, and synchronization. As a result, you get either Concurrent C or Concurrent C++, as your heart desires.
Much of the machinery is modelled on Ada's rendezvous semantics. That's powerful stuff. Some would say it's too powerful for simple applications. The performance overheads can be large. Getting away from full blown Ada to a sleeker C environment certainly helps. Beyond that, I can't comment on whether the performance penalty is too high.
I can observe that you can cut corners. You are given enough primitives to synchronize processes several different ways. Pasted as it is atop C, Concurrent C also gives you ample opportunity to get in trouble. You have to know what you're doing to avoid horrendous debugging problems.
On the plus side, the book gives lots of examples of how to do things right. Most examples are small and cleanly written, which helps. Many could use more description in the running text, which does not. The book contains exercises at regular intervals. The exercises look doable and reasonably well keyed to the material. Muck with the examples, do some of the exercises, and you will probably learn a lot.
The authors claim to have ported Concurrent C to a number of useful environments. You should be able to get your hands on a version that you can tinker with. Whether you should do production work in Concurrent C I can't say. It will certainly give you some useful experience in writing concurrent programs.
Portable Programs for Parallel Processors
James Boyle, Ralph Butler, Terence Disz, Barnett Glickfeld, Ewing Lusk, Ross Overbeek, James Patterson, and Rick Stevens, Holt, Rinehart and Winston, New York, 1987.You can look on this book as providing a kind of poor man's Concurrent C. The authors have developed a macro package that isolates concurrency control within a C program. They use the standard UNIX macro preprocessor m4 to expand the macros. Buy the hardbound version of the book and you get a diskette containing sets of these macros for a variety of machines.
The "language" is naturally restricted to what you can do by rewriting C source text with a macro preprocessor. That's not too bad since m4 lets you write what look like C function calls to invoke macros with arguments. It looks a little silly where you have to write special declarations, but what the heck. I found the code in the book to be about as readable as Concurrent C, even though the latter has a much more integrated grammar.
More to the point is the choice of primitives provided by the macro package. They seem to have accreted over time as the authors tackled progressively more demanding problems to solve. I'd have been happier if some effort had gone into tidying up the set.
Still, the macros do provide a good way to improve portability. I earlier lamented the variety of architectures you must choose among if you want truly parallel code execution. The marketplace is changing too fast for you to want to hitch your wagon to any one star, no matter how brightly it shines today. You need help in isolating implementation peculiarities. Nobody likes code that's half #ifdefs; it's almost impossible to read. So long as macros don't get too clever, they can help a lot.
So the authors deserve credit for developing a method for improving the readability of concurrent C code that must remain portable. If they haven't yet formulated an elegant language for describing concurrency, it's hard to fault them. I don't know of anyone else who has.
What they have done is produce a book that is fairly readable. It has lots of examples and reasonable good explanations. (It does not have exercises, sadly.) The code looks believable. You can learn a lot about concurrent programming by reading it and playing with the macros. You might want to give it a try.