Patchwork libstdc++/50834 - update thread safety docs w.r.t. C++11

login
register
mail settings
Submitter Jonathan Wakely
Date Oct. 24, 2011, 12:20 a.m.
Message ID <CAH6eHdRBwWWZdmE_h1cOhr-+GjHqZTzOVwempv6YD7iC2zE0pg@mail.gmail.com>
Download mbox | patch
Permalink /patch/121260/
State New
Headers show

Comments

Jonathan Wakely - Oct. 24, 2011, 12:20 a.m.
PR libstdc++/50834
        * doc/xml/manual/using.xml: Update thread safety docs w.r.t. C++11.

committed to trunk

Patch

Index: doc/xml/manual/using.xml
===================================================================
--- doc/xml/manual/using.xml	(revision 180334)
+++ doc/xml/manual/using.xml	(working copy)
@@ -1281,9 +1281,16 @@  A quick read of the relevant part of the
     <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.
        </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.
 
      // 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>