Commit ec8ab7c4 by Jonathan Wakely Committed by Jonathan Wakely

re PR libstdc++/50834 (Documentation about STL thread safety is ambiguous)

	PR libstdc++/50834
	* doc/xml/manual/using.xml: Update thread safety docs w.r.t. C++11.

From-SVN: r180359
parent a0d90b97
2011-10-22 Jonathan Wakely <jwakely.gcc@gmail.com> 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 PR libstdc++/50196
* acinclude.m4 (GLIBCXX_HAS_GTHREADS): Don't depend on _POSIX_TIMEOUTS. * acinclude.m4 (GLIBCXX_HAS_GTHREADS): Don't depend on _POSIX_TIMEOUTS.
* configure: Regenerate. * configure: Regenerate.
......
...@@ -1281,9 +1281,16 @@ A quick read of the relevant part of the GCC ...@@ -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> <section xml:id="manual.intro.using.concurrency.thread_safety" xreflabel="Thread Safety"><info><title>Thread Safety</title></info>
<para> <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> </para>
...@@ -1329,17 +1336,25 @@ gcc version 4.1.2 20070925 (Red Hat 4.1.2-33) ...@@ -1329,17 +1336,25 @@ gcc version 4.1.2 20070925 (Red Hat 4.1.2-33)
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para>The user-code must guard against concurrent method calls which may
access any particular library object's state. Typically, the <para>The user code must guard against concurrent function calls which
application programmer may infer what object locks must be held access any particular library object's state when one or more of
based on the objects referenced in a method call. Without getting 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 into great detail, here is an example which requires user-level
locks: locks:
</para> </para>
<programlisting> <programlisting>
library_class_a shared_object_a; library_class_a shared_object_a;
thread_main () { void thread_main () {
library_class_b *object_b = new library_class_b; 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.add_b (object_b); // must hold lock for shared_object_a
shared_object_a.mutate (); // 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) ...@@ -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> // 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 <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: user-level locks:
</para> </para>
<programlisting> <programlisting>
thread_main () { void thread_main () {
library_class_a object_a; library_class_a object_a;
library_class_b *object_b = new library_class_b; library_class_b *object_b = new library_class_b;
object_a.add_b (object_b); object_a.add_b (object_b);
object_a.mutate (); object_a.mutate ();
} </programlisting> } </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 <para>All library types are safe to use in a multithreaded program
thread while it uses any object visible to another thread, i.e., if objects are not shared between threads or as
treat library objects like any other shared resource. In general, long each thread carefully locks out access by any other
this requirement includes both read and write access to objects; thread while it modifies any object visible to another thread.
unless otherwise documented as safe, do not assume that two threads Unless otherwise documented, the only exceptions to these rules
may access a shared standard library object at the same time. 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> </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>
<section xml:id="manual.intro.using.concurrency.atomics" xreflabel="Atomics"><info><title>Atomics</title></info> <section xml:id="manual.intro.using.concurrency.atomics" xreflabel="Atomics"><info><title>Atomics</title></info>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment