Additions to C Rationale

Document: N1458
Date: 10 May-10
Author: P.J. Plauger

ACTION: PJ to write a rationale for N1371, Thread Unsafe Standard Functions.

Much of the Standard C library was developed before multithreading became commonplace. In an environment where memory is not shared among multiple threads of execution, few problems arise when a library function makes use of writable static data. The advent of sharing, however, introduces problems.

At the least, shared data must be protected against writes from one thread and reads from others. This requires the use of access locks, which can dramatically slow execution even when multiple threads are not running. One fix is to make writable static data unique to each thread (thread-local storage). But it is not always clear when it makes sense to do so. For example, strtok is a possible candidate for thread-local storage, but stdout is not.

Sometimes, the best choice is to simply warn about the functions that are thread unsafe because they use writable static data. The programmer can then choose whether to synchronize use of such functions or to avoid using them altogether. Thus, the C Standard often simply lists certain functions as thread unsafe, following the lead of the Posix Standard. The warnings can be important because it is not always obvious that a library function makes use of writable static data.

ACTION: PJ to write a proposal for incorporating errno, as applicable w/r/t N1371

[N1416 already proposed errno as a thread-local storage object. Here is the (very) brief rationale to accompany it.]

An excellent candidate for thread-local storage is errno, because it is set by so many calls to library functions. This is also widespread current practice on systems that support multithread programming.

ACTION: PJ to write a rationale for Threads, N1372.

RATIONALE for 17.24 Threads

With the addition of 17.16 Atomics, the C Standard has acquired the terminology needed to talk about separate threads of control accessing a shared memory. Thus, it is now possible to describe the behavior of a package of functions that lets you launch and synchronize additional threads.

The package adopted in 17.24 is intentionally minimalist and modest. It is based on a product developed at Dinkumware, Ltd. and commercially available for several years on multiple platforms. Under Windows, the implementation is just a thin layer atop Windows threads. Under Linux/Posix, it is just a thin layer atop pthreads. Thus, 17.24 describes a threads package that is effectively the lowest common denominator of facilities already available in widely used operating systems.

It is also worth observing that the threads package added to Standard C++ is based on an implementation of Boost Threads, and also developed at Dinkumware. That C++ implementation is layered atop the C threads package mentioned above. So there is at least an existence proof that Standard C threads has the same basic functionality as Standard C++ threads.

Standard C threads has been rightly criticized, particularly by the larger Posix community, as being simplistic. The argument is that anyone seriously using threads will soon find a need for the more extensive facilities of pthreads, so there is no need for this simpler package. It is indeed expected that programmers with more sophisticated needs will use the richer capabilities of the underlying OS, as they have for decades. Nevertheless, even the modest package described in 17.24 has been shown to be of use in nontrivial programs, where portability is often quite important.