diff options
-rw-r--r-- | libstdc++-v3/ChangeLog | 5 | ||||
-rw-r--r-- | libstdc++-v3/doc/xml/manual/using.xml | 106 |
2 files changed, 95 insertions, 16 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 40e89df11e0..0aba8f3b186 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,10 @@ 2011-10-22 Jonathan Wakely <jwakely.gcc@gmail.com> + PR libstdc++/50834 + * doc/xml/manual/using.xml: Update thread safety docs w.r.t. C++11. + +2011-10-22 Jonathan Wakely <jwakely.gcc@gmail.com> + PR libstdc++/50196 * acinclude.m4 (GLIBCXX_HAS_GTHREADS): Don't depend on _POSIX_TIMEOUTS. * configure: Regenerate. diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml index 02498e21cd8..49541165868 100644 --- a/libstdc++-v3/doc/xml/manual/using.xml +++ b/libstdc++-v3/doc/xml/manual/using.xml @@ -1281,9 +1281,16 @@ A quick read of the relevant part of the GCC <section xml:id="manual.intro.using.concurrency.thread_safety" xreflabel="Thread Safety"><info><title>Thread Safety</title></info> - <para> -We currently use the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.sgi.com/tech/stl/thread_safety.html">SGI STL</link> definition of thread safety. +In the terms of the 2011 C++ standard a thread-safe program is one which +does not perform any conflicting non-atomic operations on memory locations +and so does not contain any data races. +The standard places requirements on the library to ensure that no data +races are caused by the library itself or by programs which use the +library correctly (as described below). +The C++11 memory model and library requirements are a more formal version +of the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.sgi.com/tech/stl/thread_safety.html">SGI STL</link> definition of thread safety, which the library used +prior to the 2011 standard. </para> @@ -1329,17 +1336,25 @@ gcc version 4.1.2 20070925 (Red Hat 4.1.2-33) </listitem> </itemizedlist> - <para>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 + + <para>The user code must guard against concurrent function calls which + access any particular library object's state when one or more of + those accesses modifies the state. An object will be modified by + invoking a non-const member function on it or passing it as a + non-const argument to a library function. An object will not be + modified by invoking a const member function on it or passing it to + a function as a pointer- or reference-to-const. + Typically, the application + programmer may infer what object locks must be held based on the + objects referenced in a function call and whether the objects are + accessed as const or non-const. Without getting into great detail, here is an example which requires user-level locks: </para> <programlisting> library_class_a shared_object_a; - thread_main () { + void 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 @@ -1347,25 +1362,84 @@ gcc version 4.1.2 20070925 (Red Hat 4.1.2-33) // Multiple copies of thread_main() are started in independent threads.</programlisting> <para>Under the assumption that object_a and object_b are never exposed to - another thread, here is an example that should not require any + another thread, here is an example that does not require any user-level locks: </para> <programlisting> - thread_main () { + void 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 (); } </programlisting> - <para>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. + + <para>All library types are safe to use in a multithreaded program + if objects are not shared between threads or as + long each thread carefully locks out access by any other + thread while it modifies any object visible to another thread. + Unless otherwise documented, the only exceptions to these rules + are atomic operations on the types in + <filename class="headerfile"><atomic></filename> + and lock/unlock operations on the standard mutex types in + <filename class="headerfile"><mutex></filename>. These + atomic operations allow concurrent accesses to the same object + without introducing data races. + </para> + + <para>The following member functions of standard containers can be + considered to be const for the purposes of avoiding data races: + <code>begin</code>, <code>end</code>, <code>rbegin</code>, <code>rend</code>, + <code>front</code>, <code>back</code>, <code>data</code>, + <code>find</code>, <code>lower_bound</code>, <code>upper_bound</code>, + <code>equal_range</code>, <code>at</code> + and, except in associative or unordered associative containers, + <code>operator[]</code>. In other words, although they are non-const + so that they can return mutable iterators, those member functions + will not modify the container. + Accessing an iterator might cause a non-modifying access to + the container the iterator refers to (for example incrementing a + list iterator must access the pointers between nodes, which are part + of the container and so conflict with other accesses to the container). </para> + <para>Programs which follow the rules above will not encounter data + races in library code, even when using library types which share + state between distinct objects. In the example below the + <code>shared_ptr</code> objects share a reference count, but + because the code does not perform any non-const operations on the + globally-visible object, the library ensures that the reference + count updates are atomic and do not introduce data races: + </para> + <programlisting> + std::shared_ptr<int> global_sp; + + void thread_main() { + auto local_sp = global_sp; // OK, copy constructor's parameter is reference-to-const + + int i = *global_sp; // OK, operator* is const + int j = *local_sp; // OK, does not operate on global_sp + + // *global_sp = 2; // NOT OK, modifies int visible to other threads + // *local_sp = 2; // NOT OK, modifies int visible to other threads + + // global_sp.reset(); // NOT OK, reset is non-const + local_sp.reset(); // OK, does not operate on global_sp + } + + int main() { + global_sp.reset(new int(1)); + std::thread t1(thread_main); + std::thread t2(thread_main); + t1.join(); + t2.join(); + } + </programlisting> + + <para>For further details of the C++11 memory model see Hans-J. Boehm's + <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/user-faq.html">Threads + and memory model for C++</link> pages, particularly the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/threadsintro.html">introduction</link> + and <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/user-faq.html">FAQ</link>. + </para> </section> <section xml:id="manual.intro.using.concurrency.atomics" xreflabel="Atomics"><info><title>Atomics</title></info> |