Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/thread/doc/faq.xml @ 35

Last change on this file since 35 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

File size: 9.3 KB
Line 
1<?xml version="1.0" encoding="utf-8"?>
2<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
3  "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd" [
4  <!ENTITY % thread.entities SYSTEM "entities.xml">
5  %thread.entities;
6]>
7<!-- Copyright (c) 2002-2003 William E. Kempf, Michael Glassford
8     Subject to the Boost Software License, Version 1.0.
9     (See accompanying file LICENSE-1.0 or  http://www.boost.org/LICENSE-1.0)
10-->
11<section id="thread.faq" last-revision="$Date: 2007/04/24 16:11:17 $">
12  <title>Frequently Asked Questions</title>
13  <qandaset>
14    <qandaentry>
15          <question>
16            <para>Are lock objects <link
17                linkend="thread.glossary.thread-safe">thread safe</link>?</para>
18          </question>
19          <answer>
20            <para><emphasis role="bold">No!</emphasis> Lock objects are not meant to
21                be shared between threads. They are meant to be short-lived objects
22                created on automatic storage within a code block. Any other usage is
23                just likely to lead to errors and won't really be of actual benefit anyway.
24                Share <link linkend="thread.concepts.mutexes">Mutexes</link>, not
25                Locks. For more information see the <link
26                linkend="thread.rationale.locks">rationale</link> behind the
27                design for lock objects.</para>
28          </answer>
29        </qandaentry>
30    <qandaentry>
31      <question>
32            <para>Why was &Boost.Thread; modeled after (specific library
33                name)?</para>
34          </question>
35          <answer>
36            <para>It wasn't. &Boost.Thread; was designed from scratch. Extensive
37                design discussions involved numerous people representing a wide range of
38                experience across many platforms. To ensure portability, the initial
39                implements were done in parallel using POSIX Threads and the Win32
40                threading API. But the &Boost.Thread; design is very much in the spirit
41                of C++, and thus doesn't model such C based APIs.</para>
42          </answer>
43        </qandaentry>
44        <qandaentry>
45          <question>
46            <para>Why wasn't &Boost.Thread; modeled after (specific library
47            name)?</para>
48          </question>
49          <answer>
50        <para>Existing C++ libraries either seemed dangerous (often failing to
51                take advantage of prior art to reduce errors) or had excessive
52                dependencies on library components unrelated to threading. Existing C
53                libraries couldn't meet our C++ requirements, and were also missing
54                certain features. For instance, the WIN32 thread API lacks condition
55                variables, even though these are critical for the important Monitor
56                pattern &cite.SchmidtStalRohnertBuschmann;.</para>
57      </answer>
58        </qandaentry>
59        <qandaentry>
60          <question>
61            <para>Why do <link linkend="thread.concepts.mutexes">Mutexes</link>
62                have noncopyable semantics?</para>
63          </question>
64          <answer>
65        <para>To ensure that <link
66                linkend="thread.glossary.deadlock">deadlocks</link> don't occur. The
67                only logical form of copy would be to use some sort of shallow copy
68                semantics in which multiple mutex objects could refer to the same mutex
69                state. This means that if ObjA has a mutex object as part of its state
70                and ObjB is copy constructed from it, then when ObjB::foo() locks the
71                mutex it has effectively locked ObjA as well. This behavior can result
72                in deadlock. Other copy semantics result in similar problems (if you
73                think you can prove this to be wrong then supply us with an alternative
74                and we'll reconsider).</para>
75          </answer>
76        </qandaentry>
77        <qandaentry>
78          <question>
79            <para>How can you prevent <link
80                linkend="thread.glossary.deadlock">deadlock</link> from occurring when
81                a thread must lock multiple mutexes?</para>
82          </question>
83          <answer>
84            <para>Always lock them in the same order. One easy way of doing this is
85                to use each mutex's address to determine the order in which they are
86                locked. A future &Boost.Thread; concept may wrap this pattern up in a
87                reusable class.</para>
88          </answer>
89        </qandaentry>
90        <qandaentry>
91          <question>
92            <para>Don't noncopyable <link
93                linkend="thread.concepts.mutexes">Mutex</link> semantics mean that a
94                class with a mutex member will be noncopyable as well?</para>
95          </question>
96          <answer>
97            <para>No, but what it does mean is that the compiler can't generate a
98                copy constructor and assignment operator, so they will have to be coded
99                explicitly. This is a <emphasis role="bold">good thing</emphasis>,
100                however, since the compiler generated operations would not be <link
101                linkend="thread.glossary.thread-safe">thread-safe</link>. The following
102                is a simple example of a class with copyable semantics and internal
103        synchronization through a mutex member.</para>
104<programlisting>
105class counter
106{
107public:
108   // Doesn't need synchronization since there can be no references to *this
109   // until after it's constructed!
110   explicit counter(int initial_value)
111      : m_value(initial_value)
112   {
113   }
114   // We only need to synchronize other for the same reason we don't have to
115   // synchronize on construction!
116   counter(const counter&amp; other)
117   {
118      boost::mutex::scoped_lock scoped_lock(other.m_mutex);
119      m_value = other.m_value;
120   }
121   // For assignment we need to synchronize both objects!
122   const counter&amp; operator=(const counter&amp; other)
123   {
124      if (this == &amp;other)
125         return *this;
126      boost::mutex::scoped_lock lock1(&amp;m_mutex &lt; &amp;other.m_mutex ? m_mutex : other.m_mutex);
127      boost::mutex::scoped_lock lock2(&amp;m_mutex &gt; &amp;other.m_mutex ? m_mutex : other.m_mutex);
128      m_value = other.m_value;
129      return *this;
130   }
131   int value() const
132   {
133      boost::mutex::scoped_lock scoped_lock(m_mutex);
134      return m_value;
135   }
136   int increment()
137   {
138      boost::mutex::scoped_lock scoped_lock(m_mutex);
139      return ++m_value;
140   }
141private:
142   mutable boost::mutex m_mutex;
143   int m_value;
144};
145</programlisting>
146      </answer>
147        </qandaentry>
148        <qandaentry>
149          <question>
150            <para>How can you lock a <link
151                linkend="thread.concepts.mutexes">Mutex</link> member in a const member
152                function, in order to implement the Monitor Pattern?</para>
153          </question>
154          <answer>
155            <para>The Monitor Pattern &cite.SchmidtStalRohnertBuschmann; mutex
156                should simply be declared as mutable. See the example code above. The
157                internal state of mutex types could have been made mutable, with all
158                lock calls made via const functions, but this does a poor job of
159                documenting the actual semantics (and in fact would be incorrect since
160                the logical state of a locked mutex clearly differs from the logical
161                state of an unlocked mutex). Declaring a mutex member as mutable clearly
162                documents the intended semantics.</para>
163          </answer>
164        </qandaentry>
165        <qandaentry>
166          <question>
167            <para>Why supply <classname>boost::condition</classname> variables rather than
168                event variables?</para>
169          </question>
170          <answer>
171            <para>Condition variables result in user code much less prone to <link
172                linkend="thread.glossary.race-condition">race conditions</link> than
173                event variables. See <xref linkend="thread.rationale.events" /> 
174                for analysis. Also see &cite.Hoare74; and &cite.SchmidtStalRohnertBuschmann;.
175                </para>
176          </answer>
177        </qandaentry>
178        <qandaentry>
179          <question>
180            <para>Why isn't thread cancellation or termination provided?</para>
181          </question>
182          <answer>
183            <para>There's a valid need for thread termination, so at some point
184                &Boost.Thread; probably will include it, but only after we can find a
185                truly safe (and portable) mechanism for this concept.</para>
186          </answer>
187        </qandaentry>
188        <qandaentry>
189          <question>
190            <para>Is it safe for threads to share automatic storage duration (stack)
191                objects via pointers or references?</para>
192          </question>
193          <answer>
194            <para>Only if you can guarantee that the lifetime of the stack object
195                will not end while other threads might still access the object. Thus the
196                safest practice is to avoid sharing stack objects, particularly in
197                designs where threads are created and destroyed dynamically. Restrict
198                sharing of stack objects to simple designs with very clear and
199                unchanging function and thread lifetimes. (Suggested by Darryl
200                Green).</para>
201          </answer>
202        </qandaentry>
203        <qandaentry>
204          <question>
205            <para>Why has class semaphore disappeared?</para>
206          </question>
207          <answer>
208            <para>Semaphore was removed as too error prone. The same effect can be
209                achieved with greater safety by the combination of a mutex and a
210                condition variable.</para>
211          </answer>
212        </qandaentry>
213        <qandaentry>
214          <question>
215            <para>Why doesn't the thread's ctor take at least a void* to pass any
216            information along with the function? All other threading libs support
217            that and it makes Boost.Threads inferiour. </para>
218          </question>
219          <answer>
220            <para>There is no need, because Boost.Threads are superiour! First
221            thing is that its ctor doesn't take a function but a functor. That
222            means that you can pass an object with an overloaded operator() and
223            include additional data as members in that object. Beware though that
224            this object is copied, use boost::ref to prevent that. Secondly, even
225            a boost::function&lt;void (void)&gt; can carry parameters, you only have to
226            use boost::bind() to create it from any function and bind its
227            parameters.</para>
228            <para>That is also why Boost.Threads are superiour, because they
229            don't require you to pass a type-unsafe void pointer. Rather, you can
230            use the flexible Boost.Functions to create a thread entry out of
231            anything that can be called.</para>
232          </answer>
233        </qandaentry>
234  </qandaset>
235</section>
Note: See TracBrowser for help on using the repository browser.