3. Using the C++ Compiler Options
6. Creating and Using Templates
9. Improving Program Performance
10. Building Multithreaded Programs
10.1 Building Multithreaded Programs
10.1.1 Indicating Multithreaded Compilation
10.1.2 Using C++ Support Libraries With Threads and Signals
10.2 Using Exceptions in a Multithreaded Program
10.3 Sharing C++ Standard Library Objects Between Threads
10.4 Using Classic iostreams in a Multithreading Environment
10.4.1 Organization of the MT-Safe iostream Library
10.4.1.1 Public Conversion Routines
10.4.1.2 Compiling and Linking With the MT-Safe libC Library
10.4.1.3 MT-Safe iostream Restrictions
10.4.1.4 Reducing Performance Overhead of MT-Safe Classes
10.4.2 Interface Changes to the iostream Library
10.4.2.2 The New Class Hierarchy
12. Using The C++ Standard Library
13. Using the Classic iostream Library
The compiler provides the header file mbarrier.h, which defines various memory barrier intrinsics for SPARC and x86 processors. These intrinsics may be of use for developers writing multithreaded code using their own synchronization primitives. Users are advised to refer to the documentation of their processors to determine when and whether these intrinsics are necessary for their particular situation.
Memory ordering intrinsics supported by mbarrier.h:
__machine_r_barrier() — This is a read barrier. It ensures that all the load operations before the barrier will be completed before all the load operations after the barrier.
__machine_w_barrier() — This is a write barrier. It ensures that all the store operations before the barrier will be completed before all the store operations after the barrier.
__machine_rw_barrier() — This is a read—write barrier. It ensures that all the load and store operations before the barrier will be completed before all the load and store operations after the barrier.
__machine_acq_barrier() — This is a barrier with acquire semantics. It ensures that all the load operations before the barrier will be completed before all the load and store operations after the barrier.
__machine_rel_barrier() — This is a barrier with release semantics. It ensures that all the load and store operations before the barrier will be completed before all the store operations after the barrier.
__compiler_barrier() — Prevents the compiler from moving memory accesses across the barrier.
All the barrier intrinsics with the exception of the __compiler_barrier() intrinsic generate memory ordering instructions, on x86 these are mfence, sfence, or lfence instructions, on SPARC platforms these are membar instructions.
The __compiler_barrier() intrinsic generates no instructions and instead informs the compiler that all previous memory operations must be completed before any future memory operations are initiated. The practical result of this is that all non-local variables and local variables with the static storage class specifier will be stored back to memory before the barrier, and reloaded after the barrier, and the compiler will not mix memory operations from before the barrier with those after. All other barriers implicitly include the behaviour of the __compiler_barrier() intrinsic.
For example, in the following code the presence of the __compiler_barrier() intrinsic stops the compiler from merging the two loops:
#include "mbarrier.h" int thread_start[16]; void start_work() { /* Start all threads */ for (int i=0; i<8; i++) { thread_start[i]=1; } __compiler_barrier(); /* Wait for all threads to complete */ for (int i=0; i<8; i++) { while (thread_start[i]==1){} } }