summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libstdc++-v3/ChangeLog5
-rw-r--r--libstdc++-v3/doc/xml/manual/using.xml106
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">&lt;atomic&gt;</filename>
+ and lock/unlock operations on the standard mutex types in
+ <filename class="headerfile">&lt;mutex&gt;</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&lt;int&gt; 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>