OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libstdc++-v3/] [doc/] [xml/] [manual/] [shared_ptr.xml] - Blame information for rev 745

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 742 jeremybenn
2
         xml:id="std.util.memory.shared_ptr" xreflabel="shared_ptr">
3
4
 
5
shared_ptr
6
  
7
    
8
      ISO C++
9
    
10
    
11
      shared_ptr
12
    
13
  
14
15
 
16
 
17
 
18
19
The shared_ptr class template stores a pointer, usually obtained via new,
20
and implements shared ownership semantics.
21
22
 
23
Requirements
24
 
25
 
26
  
27
  
28
 
29
  
30
    The standard deliberately doesn't require a reference-counted
31
    implementation, allowing other techniques such as a
32
    circular-linked-list.
33
  
34
 
35
  
36
  
37
38
 
39
Design Issues
40
 
41
 
42
 
43
  
44
The shared_ptr code is kindly donated to GCC by the Boost
45
project and the original authors of the code. The basic design and
46
algorithms are from Boost, the notes below describe details specific to
47
the GCC implementation. Names have been uglified in this implementation,
48
but the design should be recognisable to anyone familiar with the Boost
49
1.32 shared_ptr.
50
  
51
 
52
  
53
The basic design is an abstract base class, _Sp_counted_base that
54
does the reference-counting and calls virtual functions when the count
55
drops to zero.
56
Derived classes override those functions to destroy resources in a context
57
where the correct dynamic type is known. This is an application of the
58
technique known as type erasure.
59
  
60
 
61
62
 
63
Implementation
64
 
65
 
66
  
Class Hierarchy
67
 
68
 
69
    
70
A shared_ptr<T> contains a pointer of
71
type T* and an object of type
72
__shared_count. The shared_count contains a
73
pointer of type _Sp_counted_base* which points to the
74
object that maintains the reference-counts and destroys the managed
75
resource.
76
    
77
 
78
79
 
80
81
  _Sp_counted_base<Lp>
82
  
83
    
84
The base of the hierarchy is parameterized on the lock policy (see below.)
85
_Sp_counted_base doesn't depend on the type of pointer being managed,
86
it only maintains the reference counts and calls virtual functions when
87
the counts drop to zero. The managed object is destroyed when the last
88
strong reference is dropped, but the _Sp_counted_base itself must exist
89
until the last weak reference is dropped.
90
    
91
  
92
93
 
94
95
  _Sp_counted_base_impl<Ptr, Deleter, Lp>
96
  
97
    
98
Inherits from _Sp_counted_base and stores a pointer of type Ptr
99
and a deleter of type Deleter.  _Sp_deleter is
100
used when the user doesn't supply a custom deleter. Unlike Boost's, this
101
default deleter is not "checked" because GCC already issues a warning if
102
delete is used with an incomplete type.
103
This is the only derived type used by tr1::shared_ptr<Ptr>
104
and it is never used by std::shared_ptr, which uses one of
105
the following types, depending on how the shared_ptr is constructed.
106
    
107
  
108
109
 
110
111
  _Sp_counted_ptr<Ptr, Lp>
112
  
113
    
114
Inherits from _Sp_counted_base and stores a pointer of type Ptr,
115
which is passed to delete when the last reference is dropped.
116
This is the simplest form and is used when there is no custom deleter or
117
allocator.
118
    
119
  
120
121
 
122
123
  _Sp_counted_deleter<Ptr, Deleter, Alloc>
124
  
125
    
126
Inherits from _Sp_counted_ptr and adds support for custom deleter and
127
allocator. Empty Base Optimization is used for the allocator. This class
128
is used even when the user only provides a custom deleter, in which case
129
allocator is used as the allocator.
130
    
131
  
132
133
 
134
135
  _Sp_counted_ptr_inplace<Tp, Alloc, Lp>
136
  
137
    
138
Used by allocate_shared and make_shared.
139
Contains aligned storage to hold an object of type Tp,
140
which is constructed in-place with placement new.
141
Has a variadic template constructor allowing any number of arguments to
142
be forwarded to Tp's constructor.
143
Unlike the other _Sp_counted_* classes, this one is parameterized on the
144
type of object, not the type of pointer; this is purely a convenience
145
that simplifies the implementation slightly.
146
    
147
  
148
149
 
150
151
 
152
    
153
C++11-only features are: rvalue-ref/move support, allocator support,
154
aliasing constructor, make_shared & allocate_shared. Additionally,
155
the constructors taking auto_ptr parameters are
156
deprecated in C++11 mode.
157
    
158
 
159
 
160
  
161
 
162
  
Thread Safety
163
 
164
165
The
166
Thread
167
Safety section of the Boost shared_ptr documentation says "shared_ptr
168
objects offer the same level of thread safety as built-in types."
169
The implementation must ensure that concurrent updates to separate shared_ptr
170
instances are correct even when those instances share a reference count e.g.
171
172
 
173
174
shared_ptr<A> a(new A);
175
shared_ptr<A> b(a);
176
 
177
// Thread 1     // Thread 2
178
   a.reset();      b.reset();
179
180
 
181
182
The dynamically-allocated object must be destroyed by exactly one of the
183
threads. Weak references make things even more interesting.
184
The shared state used to implement shared_ptr must be transparent to the
185
user and invariants must be preserved at all times.
186
The key pieces of shared state are the strong and weak reference counts.
187
Updates to these need to be atomic and visible to all threads to ensure
188
correct cleanup of the managed resource (which is, after all, shared_ptr's
189
job!)
190
On multi-processor systems memory synchronisation may be needed so that
191
reference-count updates and the destruction of the managed resource are
192
race-free.
193
194
 
195
196
The function _Sp_counted_base::_M_add_ref_lock(), called when
197
obtaining a shared_ptr from a weak_ptr, has to test if the managed
198
resource still exists and either increment the reference count or throw
199
bad_weak_ptr.
200
In a multi-threaded program there is a potential race condition if the last
201
reference is dropped (and the managed resource destroyed) between testing
202
the reference count and incrementing it, which could result in a shared_ptr
203
pointing to invalid memory.
204
205
206
The Boost shared_ptr (as used in GCC) features a clever lock-free
207
algorithm to avoid the race condition, but this relies on the
208
processor supporting an atomic Compare-And-Swap
209
instruction. For other platforms there are fall-backs using mutex
210
locks.  Boost (as of version 1.35) includes several different
211
implementations and the preprocessor selects one based on the
212
compiler, standard library, platform etc. For the version of
213
shared_ptr in libstdc++ the compiler and library are fixed, which
214
makes things much simpler: we have an atomic CAS or we don't, see Lock
215
Policy below for details.
216
217
 
218
  
219
 
220
  
Selecting Lock Policy
221
 
222
 
223
    
224
    
225
 
226
    
227
There is a single _Sp_counted_base class,
228
which is a template parameterized on the enum
229
__gnu_cxx::_Lock_policy.  The entire family of classes is
230
parameterized on the lock policy, right up to
231
__shared_ptr, __weak_ptr and
232
__enable_shared_from_this. The actual
233
std::shared_ptr class inherits from
234
__shared_ptr with the lock policy parameter
235
selected automatically based on the thread model and platform that
236
libstdc++ is configured for, so that the best available template
237
specialization will be used. This design is necessary because it would
238
not be conforming for shared_ptr to have an
239
extra template parameter, even if it had a default value.  The
240
available policies are:
241
    
242
 
243
   
244
     
245
       
246
       _S_Atomic
247
       
248
       
249
Selected when GCC supports a builtin atomic compare-and-swap operation
250
on the target processor (see Atomic
251
Builtins.)  The reference counts are maintained using a lock-free
252
algorithm and GCC's atomic builtins, which provide the required memory
253
synchronisation.
254
       
255
     
256
 
257
     
258
       
259
       _S_Mutex
260
       
261
       
262
The _Sp_counted_base specialization for this policy contains a mutex,
263
which is locked in add_ref_lock(). This policy is used when GCC's atomic
264
builtins aren't available so explicit memory barriers are needed in places.
265
       
266
     
267
 
268
     
269
       
270
       _S_Single
271
       
272
       
273
This policy uses a non-reentrant add_ref_lock() with no locking. It is
274
used when libstdc++ is built without --enable-threads.
275
       
276
     
277
 
278
   
279
     
280
       For all three policies, reference count increments and
281
       decrements are done via the functions in
282
       ext/atomicity.h, which detect if the program
283
       is multi-threaded.  If only one thread of execution exists in
284
       the program then less expensive non-atomic operations are used.
285
     
286
  
287
 
288
 
289
Related functions and classes
290
 
291
 
292
293
 
294
295
  dynamic_pointer_cast, static_pointer_cast,
296
const_pointer_cast
297
  
298
    
299
As noted in N2351, these functions can be implemented non-intrusively using
300
the alias constructor.  However the aliasing constructor is only available
301
in C++11 mode, so in TR1 mode these casts rely on three non-standard
302
constructors in shared_ptr and __shared_ptr.
303
In C++11 mode these constructors and the related tag types are not needed.
304
    
305
  
306
307
 
308
309
  enable_shared_from_this
310
  
311
    
312
The clever overload to detect a base class of type
313
enable_shared_from_this comes straight from Boost.
314
There is an extra overload for __enable_shared_from_this to
315
work smoothly with __shared_ptr<Tp, Lp> using any lock
316
policy.
317
    
318
  
319
320
 
321
322
  make_shared, allocate_shared
323
  
324
    
325
make_shared simply forwards to allocate_shared
326
with std::allocator as the allocator.
327
Although these functions can be implemented non-intrusively using the
328
alias constructor, if they have access to the implementation then it is
329
possible to save storage and reduce the number of heap allocations. The
330
newly constructed object and the _Sp_counted_* can be allocated in a single
331
block and the standard says implementations are "encouraged, but not required,"
332
to do so. This implementation provides additional non-standard constructors
333
(selected with the type _Sp_make_shared_tag) which create an
334
object of type _Sp_counted_ptr_inplace to hold the new object.
335
The returned shared_ptr<A> needs to know the address of the
336
new A object embedded in the _Sp_counted_ptr_inplace,
337
but it has no way to access it.
338
This implementation uses a "covert channel" to return the address of the
339
embedded object when get_deleter<_Sp_make_shared_tag>()
340
is called.  Users should not try to use this.
341
As well as the extra constructors, this implementation also needs some
342
members of _Sp_counted_deleter to be protected where they could otherwise
343
be private.
344
    
345
  
346
347
 
348
349
 
350
351
 
352
353
 
354
Use
355
 
356
 
357
  
Examples
358
 
359
    
360
      Examples of use can be found in the testsuite, under
361
      testsuite/tr1/2_general_utilities/shared_ptr,
362
      testsuite/20_util/shared_ptr
363
      and
364
      testsuite/20_util/weak_ptr.
365
    
366
  
367
 
368
  
Unresolved Issues
369
 
370
    
371
      The shared_ptr atomic access
372
      clause in the C++11 standard is not implemented in GCC.
373
    
374
 
375
    
376
      The _S_single policy uses atomics when used in MT
377
      code, because it uses the same dispatcher functions that check
378
      __gthread_active_p(). This could be
379
      addressed by providing template specialisations for some members
380
      of _Sp_counted_base<_S_single>.
381
    
382
 
383
    
384
      Unlike Boost, this implementation does not use separate classes
385
      for the pointer+deleter and pointer+deleter+allocator cases in
386
      C++11 mode, combining both into _Sp_counted_deleter and using
387
      allocator when the user doesn't specify
388
      an allocator.  If it was found to be beneficial an additional
389
      class could easily be added.  With the current implementation,
390
      the _Sp_counted_deleter and __shared_count constructors taking a
391
      custom deleter but no allocator are technically redundant and
392
      could be removed, changing callers to always specify an
393
      allocator. If a separate pointer+deleter class was added the
394
      __shared_count constructor would be needed, so it has been kept
395
      for now.
396
    
397
 
398
    
399
      The hack used to get the address of the managed object from
400
      _Sp_counted_ptr_inplace::_M_get_deleter()
401
      is accessible to users. This could be prevented if
402
      get_deleter<_Sp_make_shared_tag>()
403
      always returned NULL, since the hack only needs to work at a
404
      lower level, not in the public API. This wouldn't be difficult,
405
      but hasn't been done since there is no danger of accidental
406
      misuse: users already know they are relying on unsupported
407
      features if they refer to implementation details such as
408
      _Sp_make_shared_tag.
409
    
410
 
411
    
412
      tr1::_Sp_deleter could be a private member of tr1::__shared_count but it
413
      would alter the ABI.
414
    
415
 
416
  
417
 
418
419
 
420
Acknowledgments
421
 
422
 
423
  
424
    The original authors of the Boost shared_ptr, which is really nice
425
    code to work with, Peter Dimov in particular for his help and
426
    invaluable advice on thread safety.  Phillip Jordan and Paolo
427
    Carlini for the lock policy implementation.
428
  
429
 
430
431
 
432
Bibliography
433
 
434
 
435
  
436
      </code></pre></td>
      </tr>
      <tr valign="middle">
         <td>437</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>        <link xmlns:xlink="http://www.w3.org/1999/xlink"</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>438</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>              xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm"></code></pre></td>
      </tr>
      <tr valign="middle">
         <td>439</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>      Improving shared_ptr for C++0x, Revision 2</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>440</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>        </link></code></pre></td>
      </tr>
      <tr valign="middle">
         <td>441</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>      
442
 
443
    
444
      N2351
445
    
446
  
447
 
448
  
449
      </code></pre></td>
      </tr>
      <tr valign="middle">
         <td>450</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>        <link xmlns:xlink="http://www.w3.org/1999/xlink"</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>451</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>              xlink:href="http://open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2456.html"></code></pre></td>
      </tr>
      <tr valign="middle">
         <td>452</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>      C++ Standard Library Active Issues List</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>453</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>        </link></code></pre></td>
      </tr>
      <tr valign="middle">
         <td>454</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>      
455
 
456
    
457
      N2456
458
    
459
  
460
 
461
  
462
      </code></pre></td>
      </tr>
      <tr valign="middle">
         <td>463</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>        <link xmlns:xlink="http://www.w3.org/1999/xlink"</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>464</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>              xlink:href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf"></code></pre></td>
      </tr>
      <tr valign="middle">
         <td>465</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>      Working Draft, Standard for Programming Language C++</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>466</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>        </link></code></pre></td>
      </tr>
      <tr valign="middle">
         <td>467</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>      
468
    
469
      N2461
470
    
471
  
472
 
473
  
474
      </code></pre></td>
      </tr>
      <tr valign="middle">
         <td>475</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>        <link xmlns:xlink="http://www.w3.org/1999/xlink"</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>476</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>              xlink:href="http://boost.org/libs/smart_ptr/shared_ptr.htm"></code></pre></td>
      </tr>
      <tr valign="middle">
         <td>477</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>      Boost C++ Libraries documentation, shared_ptr</code></pre></td>
      </tr>
      <tr valign="middle">
         <td>478</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>        </link></code></pre></td>
      </tr>
      <tr valign="middle">
         <td>479</td>
         <td></td>
         <td></td>
         <td class="code"><pre><code>      
480
 
481
    
482
      N2461
483
    
484
  
485
 
486
487
 
488

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.