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