Blame view

3rdparty/boost_1_81_0/doc/html/signals2/thread-safety.html 15.7 KB
e6ccf0ce   Hu Chunming   提交三方库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  <html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Thread-Safety</title>
  <link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
  <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
  <link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
  <link rel="up" href="../signals2.html" title="Chapter 34. Boost.Signals2">
  <link rel="prev" href="../boost/signals2/trackable.html" title="Class trackable">
  <link rel="next" href="faq.html" title="Frequently Asked Questions">
  </head>
  <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
  <table cellpadding="2" width="100%"><tr>
  <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
  <td align="center"><a href="../../../index.html">Home</a></td>
  <td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
  <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
  <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
  <td align="center"><a href="../../../more/index.htm">More</a></td>
  </tr></table>
  <hr>
  <div class="spirit-nav">
  <a accesskey="p" href="../boost/signals2/trackable.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../signals2.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="faq.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
  </div>
  <div class="section">
  <div class="titlepage"><div><div><h2 class="title" style="clear: both">
  <a name="signals2.thread-safety"></a>Thread-Safety</h2></div></div></div>
  <div class="toc"><dl class="toc">
  <dt><span class="section"><a href="thread-safety.html#id-1.3.35.7.2">Introduction</a></span></dt>
  <dt><span class="section"><a href="thread-safety.html#id-1.3.35.7.3">Signals and combiners</a></span></dt>
  <dt><span class="section"><a href="thread-safety.html#id-1.3.35.7.4">Connections and other classes</a></span></dt>
  </dl></div>
  <div class="section">
  <div class="titlepage"><div><div><h3 class="title">
  <a name="id-1.3.35.7.2"></a>Introduction</h3></div></div></div>
  <p>
        The primary motivation for Boost.Signals2 is to provide a version of
        the original Boost.Signals library which can be used safely in a
        multi-threaded environment.
        This is achieved primarily through two changes from the original Boost.Signals
        API.  One is the introduction of a new automatic connection management scheme
        relying on <code class="computeroutput"><a class="link" href="../boost/shared_ptr.html" title="Class template shared_ptr">shared_ptr</a></code> and <code class="computeroutput">weak_ptr</code>,
        as described in the <a class="link" href="tutorial.html#signals2.tutorial.connection-management" title="Automatic Connection Management (Intermediate)">tutorial</a>.
        The second change was the introduction of a <code class="computeroutput">Mutex</code> template type
        parameter to the <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html" title="Class template signal">signal</a></code> class.  This section details how
        the library employs these changes to provide thread-safety, and
        the limits of the provided thread-safety.
      </p>
  </div>
  <div class="section">
  <div class="titlepage"><div><div><h3 class="title">
  <a name="id-1.3.35.7.3"></a>Signals and combiners</h3></div></div></div>
  <p>
        Each signal object default-constructs a <code class="computeroutput">Mutex</code> object to protect
        its internal state.  Furthermore, a <code class="computeroutput">Mutex</code> is created
        each time a new slot is connected to the signal, to protect the
        associated signal-slot connection.
      </p>
  <p>
        A signal's mutex is automatically locked whenever any of the
        signal's methods are called.  The mutex is usually held until the
        method completes, however there is one major exception to this rule.  When
        a signal is invoked by calling
        <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_35_6_9_3_1_2_25_1-bb">signal::operator()</a></code>,
        the invocation first acquires a lock on the signal's mutex.  Then
        it obtains a handle to the signal's slot list and combiner.  Next
        it releases the signal's mutex, before invoking the combiner to
        iterate through the slot list.  Thus no mutexes are held by the
        signal while a slot is executing.  This design choice
        makes it impossible for user code running in a slot
        to deadlock against any of the
        mutexes used internally by the Boost.Signals2 library.
        It also prevents slots from accidentally causing
        recursive locking attempts on any of the library's internal mutexes.
        Therefore, if you invoke a signal concurrently from multiple threads,
        it is possible for the signal's combiner to be invoked concurrently
        and thus the slots to execute concurrently.
      </p>
  <p>
        During a combiner invocation, the following steps are performed in order to
        find the next callable slot while iterating through the signal's
        slot list.
      </p>
  <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
  <li class="listitem"><p>The <code class="computeroutput">Mutex</code> associated with the connection to the
            slot is locked.</p></li>
  <li class="listitem"><p>All the tracked <code class="computeroutput">weak_ptr</code> associated with the
            slot are copied into temporary <code class="computeroutput"><a class="link" href="../boost/shared_ptr.html" title="Class template shared_ptr">shared_ptr</a></code> which
            will be kept alive until the invocation is done with the slot.  If this fails due
            to any of the
            <code class="computeroutput">weak_ptr</code> being expired, the connection is
            automatically disconnected.  Therefore a slot will never be run
            if any of its tracked <code class="computeroutput">weak_ptr</code> have expired,
            and none of its tracked <code class="computeroutput">weak_ptr</code> will
            expire while the slot is running.
          </p></li>
  <li class="listitem"><p>
            The slot's connection is checked to see if it is blocked
            or disconnected, and then the connection's mutex is unlocked.  If the connection
            was either blocked or disconnected, we
            start again from the beginning with the next slot in the slot list.
            Otherwise, we commit to executing the slot when the combiner next
            dereferences the slot call iterator (unless the combiner should increment
            the iterator without ever dereferencing it).
          </p></li>
  </ul></div>
  <p>
        Note that since we unlock the connection's mutex before executing
        its associated slot, it is possible a slot will still be executing
        after it has been disconnected by a
        <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html#id-1_3_35_6_2_1_1_1_8_1-bb">connection::disconnect</a>()</code>, if
        the disconnect was called concurrently with signal invocation.
      </p>
  <p>
        You may have noticed above that during signal invocation, the invocation only
        obtains handles to the signal's slot list and combiner while holding the
        signal's mutex.  Thus concurrent signal invocations may still wind up
        accessing the
        same slot list and combiner concurrently.  So what happens if the slot list is modified,
        for example by connecting a new slot, while a signal
        invocation is in progress concurrently?  If the slot list is already in use,
        the signal performs a deep copy of the slot list before modifying it.
        Thus the a concurrent signal invocation will continue to use the old unmodified slot list,
        undisturbed by modifications made to the newly created deep copy of the slot list.
        Future signal invocations will receive a handle to the newly created deep
        copy of the slot list, and the old slot list will be destroyed once it
        is no longer in use.  Similarly, if you change a signal's combiner with
        <code class="computeroutput"><a class="link" href="../boost/signals2/signal.html#id-1_3_35_6_9_3_1_2_26_2-bb">signal::set_combiner</a></code>
        while a signal invocation is running concurrently, the concurrent
        signal invocation will continue to use the old combiner undisturbed,
        while future signal invocations will receive a handle to the new combiner.
      </p>
  <p>
        The fact that concurrent signal invocations use the same combiner object
        means you need to insure any custom combiner you write is thread-safe.
        So if your combiner maintains state which is modified when the combiner
        is invoked, you
        may need to protect that state with a mutex.  Be aware, if you hold
        a mutex in your combiner while dereferencing slot call iterators,
        you run the risk of deadlocks and recursive locking if any of
        the slots cause additional mutex locking to occur.  One way to avoid
        these perils is for your combiner to release any locks before
        dereferencing a slot call iterator.  The combiner classes provided by
        the Boost.Signals2 library are all thread-safe, since they do not maintain
        any state across invocations.
      </p>
  <p>
        Suppose a user writes a slot which connects another slot to the invoking signal.
        Will the newly connected slot be run during the same signal invocation in
        which the new connection was made?  The answer is no.  Connecting a new slot
        modifies the signal's slot list, and as explained above, a signal invocation
        already in progress will not see any modifications made to the slot list.
      </p>
  <p>
        Suppose a user writes a slot which disconnects another slot from the invoking signal.
        Will the disconnected slot be prevented from running during the same signal invocation,
        if it appears later in the slot list than the slot which disconnected it?
        This time the answer is yes.  Even if the disconnected slot is still
        present in the signal's slot list, each slot is checked to see if it is
        disconnected or blocked immediately before it is executed (or not executed as
        the case may be), as was described in more detail above.
      </p>
  </div>
  <div class="section">
  <div class="titlepage"><div><div><h3 class="title">
  <a name="id-1.3.35.7.4"></a>Connections and other classes</h3></div></div></div>
  <p>
        The methods of the <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html" title="Class connection">signals2::connection</a></code> class are thread-safe,
        with the exception of assignment and swap.  This is achived via locking the mutex
        associated with the object's underlying signal-slot connection.  Assignment and
        swap are not thread-safe because the mutex protects the underlying connection
        which a <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html" title="Class connection">signals2::connection</a></code> object references, not
        the <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html" title="Class connection">signals2::connection</a></code> object itself.  That is,
        there may be many copies of a <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html" title="Class connection">signals2::connection</a></code> object,
        all of which reference the same underlying connection.  There is not a mutex
        for each <code class="computeroutput"><a class="link" href="../boost/signals2/connection.html" title="Class connection">signals2::connection</a></code> object, there is only
        a single mutex protecting the underlying connection they reference.
      </p>
  <p>The <code class="computeroutput"><a class="link" href="../boost/signals2/shared_connection_block.html" title="Class shared_connection_block">shared_connection_block</a></code> class obtains some thread-safety
        from the <code class="computeroutput">Mutex</code> protecting the underlying connection which is blocked
        and unblocked.  The internal reference counting which is used to keep track of
        how many <code class="computeroutput"><a class="link" href="../boost/signals2/shared_connection_block.html" title="Class shared_connection_block">shared_connection_block</a></code> objects are asserting
        blocks on their underlying connection is also thread-safe (the implementation
        relies on <code class="computeroutput"><a class="link" href="../boost/shared_ptr.html" title="Class template shared_ptr">shared_ptr</a></code> for the reference counting).
        However, individual <code class="computeroutput"><a class="link" href="../boost/signals2/shared_connection_block.html" title="Class shared_connection_block">shared_connection_block</a></code> objects
        should not be accessed concurrently by multiple threads.  As long as two
        threads each have their own <code class="computeroutput"><a class="link" href="../boost/signals2/shared_connection_block.html" title="Class shared_connection_block">shared_connection_block</a></code> object,
        then they may use them in safety, even if both <code class="computeroutput"><a class="link" href="../boost/signals2/shared_connection_block.html" title="Class shared_connection_block">shared_connection_block</a></code>
        objects are copies and refer to the same underlying connection.
      </p>
  <p>
        The <code class="computeroutput"><a class="link" href="../boost/signals2/slot.html" title="Class template slot">signals2::slot</a></code> class has no internal mutex locking
        built into it.  It is expected that slot objects will be created then
        connected to a signal in a single thread.  Once they have been copied into
        a signal's slot list, they are protected by the mutex associated with
        each signal-slot connection.
      </p>
  <p>The <code class="computeroutput"><a class="link" href="../boost/signals2/trackable.html" title="Class trackable">signals2::trackable</a></code> class does NOT provide
        thread-safe automatic connection management.  In particular, it leaves open the
        possibility of a signal invocation calling into a partially destructed object
        if the trackable-derived object is destroyed in a different thread from the
        one invoking the signal.
        <code class="computeroutput"><a class="link" href="../boost/signals2/trackable.html" title="Class trackable">signals2::trackable</a></code> is only provided as a convenience
        for porting single-threaded code from Boost.Signals to Boost.Signals2.
      </p>
  </div>
  </div>
  <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
  <td align="left"><p><small>Last revised: June 12, 2007 at 14:01:23 -0400</small></p></td>
  <td align="right"><div class="copyright-footer">Copyright © 2001-2004 Douglas Gregor<br>Copyright © 2007-2009 Frank Mori Hess<p>Distributed under the Boost
      Software License, Version 1.0. (See accompanying file
      <code class="filename">LICENSE_1_0.txt</code> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)</p>
  </div></td>
  </tr></table>
  <hr>
  <div class="spirit-nav">
  <a accesskey="p" href="../boost/signals2/trackable.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../signals2.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="faq.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
  </div>
  </body>
  </html>