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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [libstdc++-v3/] [doc/] [xml/] [manual/] [shared_ptr.xml] - Blame information for rev 424

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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