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<T></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<Lp></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<Ptr, Deleter, Lp></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<Ptr></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<Ptr, Lp></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<Ptr, Deleter, Alloc></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<Tp, Alloc, Lp></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 & 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<A> a(new A); 192shared_ptr<A> 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<Tp, Lp></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<A></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<_Sp_make_shared_tag>()</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<Lp></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<Ptr, Deleter, Lp></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<Ptr></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<_S_single></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<_Sp_make_shared_tag>()</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