X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Fdoc%2Fhtml%2Fmanual%2Fusing_concurrency.html;fp=libstdc%2B%2B-v3%2Fdoc%2Fhtml%2Fmanual%2Fusing_concurrency.html;h=2ddde83a1a147c8cb3ea35efbac55e57df2591fd;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=0000000000000000000000000000000000000000;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/libstdc++-v3/doc/html/manual/using_concurrency.html b/libstdc++-v3/doc/html/manual/using_concurrency.html new file mode 100644 index 00000000..2ddde83a --- /dev/null +++ b/libstdc++-v3/doc/html/manual/using_concurrency.html @@ -0,0 +1,219 @@ + + +
This section discusses issues surrounding the proper compilation + of multithreaded applications which use the Standard C++ + library. This information is GCC-specific since the C++ + standard does not address matters of multithreaded applications. +
All normal disclaimers aside, multithreaded C++ application are
+ only supported when libstdc++ and all user code was built with
+ compilers which report (via gcc/g++ -v
) the same thread
+ model and that model is not single. As long as your
+ final application is actually single-threaded, then it should be
+ safe to mix user code built with a thread model of
+ single with a libstdc++ and other C++ libraries built
+ with another thread model useful on the platform. Other mixes
+ may or may not work but are not considered supported. (Thus, if
+ you distribute a shared C++ library in binary form only, it may
+ be best to compile it with a GCC configured with
+ --enable-threads for maximal interchangeability and usefulness
+ with a user population that may have built GCC with either
+ --enable-threads or --disable-threads.)
+
When you link a multithreaded application, you will probably + need to add a library or flag to g++. This is a very + non-standardized area of GCC across ports. Some ports support a + special flag (the spelling isn't even standardized yet) to add + all required macros to a compilation (if any such flags are + required then you must provide the flag for all compilations not + just linking) and link-library additions and/or replacements at + link time. The documentation is weak. Here is a quick summary + to display how ad hoc this is: On Solaris, both -pthreads and + -threads (with subtly different meanings) are honored. On OSF, + -pthread and -threads (with subtly different meanings) are + honored. On Linux/i386, -pthread is honored. On FreeBSD, + -pthread is honored. Some other ports use other switches. + AFAIK, none of this is properly documented anywhere other than + in ``gcc -dumpspecs'' (look at lib and cpp entries). +
+We currently use the SGI STL definition of thread safety. +
The library strives to be thread-safe when all of the following + conditions are met: +
The system's libc is itself thread-safe, +
+ The compiler in use reports a thread model other than
+ 'single'. This can be tested via output from gcc
+ -v
. Multi-thread capable versions of gcc output
+ something like this:
+
+%gcc -v +Using built-in specs. +... +Thread model: posix +gcc version 4.1.2 20070925 (Red Hat 4.1.2-33) +
Look for "Thread model" lines that aren't equal to "single."
+ Requisite command-line flags are used for atomic operations
+ and threading. Examples of this include -pthread
+ and -march=native
, although specifics vary
+ depending on the host environment. See Machine
+ Dependent Options.
+
+ An implementation of atomicity.h functions + exists for the architecture in question. See the internals documentation for more details. +
The user-code must guard against concurrent method calls which may + access any particular library object's state. Typically, the + application programmer may infer what object locks must be held + based on the objects referenced in a method call. Without getting + into great detail, here is an example which requires user-level + locks: +
+ library_class_a shared_object_a; + + thread_main () { + library_class_b *object_b = new library_class_b; + shared_object_a.add_b (object_b); // must hold lock for shared_object_a + shared_object_a.mutate (); // must hold lock for shared_object_a + } + + // Multiple copies of thread_main() are started in independent threads.
Under the assumption that object_a and object_b are never exposed to + another thread, here is an example that should not require any + user-level locks: +
+ thread_main () { + library_class_a object_a; + library_class_b *object_b = new library_class_b; + object_a.add_b (object_b); + object_a.mutate (); + }
All library objects are safe to use in a multithreaded program as + long as each thread carefully locks out access by any other + thread while it uses any object visible to another thread, i.e., + treat library objects like any other shared resource. In general, + this requirement includes both read and write access to objects; + unless otherwise documented as safe, do not assume that two threads + may access a shared standard library object at the same time. +
See chapters 17 (library + introduction), 23 + (containers), and 27 (I/O) for + more information. +
I'll assume that you have already read the + general notes on library threads, + and the + notes on threaded container + access (you might not think of an I/O stream as a container, but + the points made there also hold here). If you have not read them, + please do so first. +
This gets a bit tricky. Please read carefully, and bear with me. +
A wrapper
+ type called __basic_file
provides our abstraction layer
+ for the std::filebuf
classes. Nearly all decisions dealing
+ with actual input and output must be made in __basic_file
.
+
A generic locking mechanism is somewhat in place at the filebuf layer, + but is not used in the current code. Providing locking at any higher + level is akin to providing locking within containers, and is not done + for the same reasons (see the links above). +
The __basic_file type is simply a collection of small wrappers around
+ the C stdio layer (again, see the link under Structure). We do no
+ locking ourselves, but simply pass through to calls to fopen
,
+ fwrite
, and so forth.
+
So, for 3.0, the question of "is multithreading safe for I/O" + must be answered with, "is your platform's C library threadsafe + for I/O?" Some are by default, some are not; many offer multiple + implementations of the C library with varying tradeoffs of threadsafety + and efficiency. You, the programmer, are always required to take care + with multiple threads. +
(As an example, the POSIX standard requires that C stdio FILE*
+ operations are atomic. POSIX-conforming C libraries (e.g, on Solaris
+ and GNU/Linux) have an internal mutex to serialize operations on
+ FILE*s. However, you still need to not do stupid things like calling
+ fclose(fs)
in one thread followed by an access of
+ fs
in another.)
+
So, if your platform's C library is threadsafe, then your
+ fstream
I/O operations will be threadsafe at the lowest
+ level. For higher-level operations, such as manipulating the data
+ contained in the stream formatting classes (e.g., setting up callbacks
+ inside an std::ofstream
), you need to guard such accesses
+ like any other critical shared resource.
+
A + second choice may be available for I/O implementations: libio. This is + disabled by default, and in fact will not currently work due to other + issues. It will be revisited, however. +
The libio code is a subset of the guts of the GNU libc (glibc) I/O
+ implementation. When libio is in use, the __basic_file
+ type is basically derived from FILE. (The real situation is more
+ complex than that... it's derived from an internal type used to
+ implement FILE. See libio/libioP.h to see scary things done with
+ vtbls.) The result is that there is no "layer" of C stdio
+ to go through; the filebuf makes calls directly into the same
+ functions used to implement fread
, fwrite
,
+ and so forth, using internal data structures. (And when I say
+ "makes calls directly," I mean the function is literally
+ replaced by a jump into an internal function. Fast but frightening.
+ *grin*)
+
Also, the libio internal locks are used. This requires pulling in + large chunks of glibc, such as a pthreads implementation, and is one + of the issues preventing widespread use of libio as the libstdc++ + cstdio implementation. +
But we plan to make this work, at least as an option if not a future + default. Platforms running a copy of glibc with a recent-enough + version will see calls from libstdc++ directly into the glibc already + installed. For other platforms, a copy of the libio subsection will + be built and included in libstdc++. +
This section discusses issues surrounding the design of + multithreaded applications which use Standard C++ containers. + All information in this section is current as of the gcc 3.0 + release and all later point releases. Although earlier gcc + releases had a different approach to threading configuration and + proper compilation, the basic code design rules presented here + were similar. For information on all other aspects of + multithreading as it relates to libstdc++, including details on + the proper compilation of threaded code (and compatibility between + threaded and non-threaded code), see Chapter 17. +
Two excellent pages to read when working with the Standard C++ + containers and threads are + SGI's + http://www.sgi.com/tech/stl/thread_safety.html and + SGI's + http://www.sgi.com/tech/stl/Allocators.html. +
However, please ignore all discussions about the user-level + configuration of the lock implementation inside the STL + container-memory allocator on those pages. For the sake of this + discussion, libstdc++ configures the SGI STL implementation, + not you. This is quite different from how gcc pre-3.0 worked. + In particular, past advice was for people using g++ to + explicitly define _PTHREADS or other macros or port-specific + compilation options on the command line to get a thread-safe + STL. This is no longer required for any port and should no + longer be done unless you really know what you are doing and + assume all responsibility. +
Since the container implementation of libstdc++ uses the SGI + code, we use the same definition of thread safety as SGI when + discussing design. A key point that beginners may miss is the + fourth major paragraph of the first page mentioned above + ("For most clients,"...), which points out that + locking must nearly always be done outside the container, by + client code (that'd be you, not us). There is a notable + exceptions to this rule. Allocators called while a container or + element is constructed uses an internal lock obtained and + released solely within libstdc++ code (in fact, this is the + reason STL requires any knowledge of the thread configuration). +
For implementing a container which does its own locking, it is + trivial to provide a wrapper class which obtains the lock (as + SGI suggests), performs the container operation, and then + releases the lock. This could be templatized to a certain + extent, on the underlying container and/or a locking + mechanism. Trying to provide a catch-all general template + solution would probably be more trouble than it's worth. +
The STL implementation is currently configured to use the + high-speed caching memory allocator. Some people like to + test and/or normally run threaded programs with a different + default. For all details about how to globally override this + at application run-time see here. +
There is a better way (not standardized yet): It is possible to + force the malloc-based allocator on a per-case-basis for some + application code. The library team generally believes that this + is a better way to tune an application for high-speed using this + implementation of the STL. There is + more information on allocators here. +