Compare commits

...

528 Commits

Author SHA1 Message Date
Beman Dawes
3e765e69b9 Boost 1.42.0
[SVN r59432]
2010-02-02 20:03:43 +00:00
Peter Dimov
f4386409d9 Merge [58275], [58306] to release.
[SVN r58380]
2009-12-14 17:44:19 +00:00
Peter Dimov
ba349679f3 Merge [58123], [58127], [58128] to release. Fixes #3666.
[SVN r58195]
2009-12-06 17:50:28 +00:00
Peter Dimov
a3b84f8586 Merge [58094] to release.
[SVN r58122]
2009-12-03 17:50:37 +00:00
Peter Dimov
b0fd8a6b08 Merge [57957] to release. Fixes #3570.
[SVN r58067]
2009-11-30 20:34:39 +00:00
Peter Dimov
4f5062004a Merge [57954], [57955] to release.
[SVN r58066]
2009-11-30 20:30:22 +00:00
Peter Dimov
f040bed751 Merge [57953] to release. Fixes #2681.
[SVN r58065]
2009-11-30 20:25:01 +00:00
Peter Dimov
2f8945a885 Merge [57951] to release. Fixes #3351.
[SVN r58064]
2009-11-30 20:20:52 +00:00
Peter Dimov
2bd0778778 Merge [57949] to release. Fixes #3678. Fixes #3341.
[SVN r58063]
2009-11-30 20:17:14 +00:00
Peter Dimov
eec640bfd7 Merge [57520] to release. Fixes #2962.
[SVN r57960]
2009-11-26 22:10:30 +00:00
Peter Dimov
754fd941ee Merge [57950], [57952] to release. Fixes #3404. Fixes #3456.
[SVN r57959]
2009-11-26 21:58:16 +00:00
Troy D. Straszheim
e94f64039d rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release.
[SVN r56941]
2009-10-17 01:10:45 +00:00
Peter Dimov
63b17c24ea Merge [51909], [51912], [52937], [53672] to release.
[SVN r55479]
2009-08-08 23:21:15 +00:00
Troy D. Straszheim
8a421c2098 Add basic copyright/license to keep cmake out of the inspection report
[SVN r55095]
2009-07-22 21:51:01 +00:00
Troy D. Straszheim
5fa1cbf6e1 shared_ptr and bind cmake tweaks
[SVN r53001]
2009-05-14 20:20:34 +00:00
Joaquín M López Muñoz
9f30442d1e merged [52456], [52457] and [52464] from trunk
[SVN r52486]
2009-04-19 10:17:50 +00:00
Peter Dimov
a4293f9dfa Merge [52454] to release. Fixes #2951.
[SVN r52472]
2009-04-18 21:32:43 +00:00
David Deakins
28de0cb1e3 Have config/select_stdlib_config.hpp and config/stdlib/stlport.hpp use <cstddef> instead of <utility> to determine which standard library is in use. For std lib implementations that rely on Boost components like TypeTraits, Bind, Function, or SmartPtr, this helps to avoid circular header dependency issues, since <cstddef> is much less likely to pull in Boost libraries than <utility>.
In get_pointer.hpp, switched to using <boost/config/no_tr1/memory.hpp> instead of using <memory> directly.  As above, this helps avoid circular header dependency issues in Boost-supplemented std libs (specifically it avoids issues when <memory> pulls in pieces of Boost.SmartPtr).

These two changes were made in response to testing done with STLport 5.2.1 using the _STLP_USE_BOOST_SUPPORT option.

[SVN r52221]
2009-04-06 21:25:18 +00:00
Peter Dimov
a1b4fc8d95 Merge [51978], [51985] to release. Closes #2885.
[SVN r52016]
2009-03-27 13:10:46 +00:00
Peter Dimov
77971c6ff5 Merge [51686] to release.
[SVN r51847]
2009-03-18 23:02:27 +00:00
Frank Mori Hess
1742c37942 Merged [51699] and [51700] from trunk to release.
Closes #1897


[SVN r51703]
2009-03-11 15:08:14 +00:00
Peter Dimov
31e06b4a1d Merge [51643] to release. Fixes #2813.
[SVN r51688]
2009-03-10 18:26:57 +00:00
Peter Dimov
22f1b092c9 Merge [51581] to release. Fixes #2126. Fixes #2584.
[SVN r51632]
2009-03-05 23:06:17 +00:00
Peter Dimov
5a2771e585 Merge [51518] to release. Closes #2814.
[SVN r51539]
2009-03-02 16:45:22 +00:00
Peter Dimov
dad59f3325 Merge [51517] to release. Closes #2525.
[SVN r51538]
2009-03-02 16:42:28 +00:00
Peter Dimov
bad394b1e9 Merge [51516] to release. Closes #2662.
[SVN r51537]
2009-03-02 16:39:53 +00:00
Peter Dimov
f93110620a Merge [51515] to release. Closes #2675.
[SVN r51536]
2009-03-02 16:37:31 +00:00
Peter Dimov
6be1e3fceb Merge [51514] to release. Closes #2394.
[SVN r51535]
2009-03-02 16:35:06 +00:00
Peter Dimov
cf91287732 Merge [51509], [51519] to release. Closes #2239.
[SVN r51531]
2009-03-02 16:22:16 +00:00
Peter Dimov
0da6902267 Move smart_ptr into boost/smart_ptr/*.hpp (refs #2239).
[SVN r51509]
2009-03-01 16:00:42 +00:00
Peter Dimov
10f6ff8b77 Sync smart_ptr/test/Jamfile.v2 with release.
[SVN r51486]
2009-02-28 21:08:25 +00:00
Peter Dimov
13f91c15f0 Sync enable_shared_from_this.hpp and shared_ptr.hpp with release.
[SVN r51485]
2009-02-28 20:02:12 +00:00
Peter Dimov
a2c5208b8e Sync shared_count.hpp with trunk.
[SVN r51484]
2009-02-28 19:59:56 +00:00
Troy D. Straszheim
55583ac749 merge of cmake build files from trunk per beman
[SVN r50756]
2009-01-24 18:57:20 +00:00
Michael A. Jackson
c40b306647 Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use.
[SVN r49627]
2008-11-07 17:02:56 +00:00
Michael A. Jackson
d9b9921d23 Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor
[SVN r49510]
2008-11-01 13:15:41 +00:00
Nicola Musatti
6f91ea87c3 CodeGear patch. Fixes #2342
[SVN r49320]
2008-10-13 19:22:17 +00:00
Nicola Musatti
ed79000ea8 Patch from Ticket #2342
[SVN r49153]
2008-10-06 20:17:18 +00:00
Peter Dimov
6e804e64b8 Merge 48832-48840 from trunk.
[SVN r48989]
2008-09-28 15:05:17 +00:00
Peter Dimov
395766e2d3 Fix #2315.
[SVN r48839]
2008-09-17 22:59:07 +00:00
Peter Dimov
774332f85a Fix #2263. See also [48835].
[SVN r48838]
2008-09-17 22:53:53 +00:00
Peter Dimov
f5990cab65 Fix #1758. V9 is the default for g++ 4.2 or later, on 4.1 and earlier do not attempt to use CAS on V8.
[SVN r48837]
2008-09-17 22:49:18 +00:00
Peter Dimov
6175baf858 Fix #2000.
[SVN r48836]
2008-09-17 22:43:14 +00:00
Peter Dimov
2fb567b3f2 Fix #2336.
[SVN r48835]
2008-09-17 22:37:13 +00:00
Peter Dimov
2b25579338 Fix #2310.
[SVN r48834]
2008-09-17 22:31:13 +00:00
Peter Dimov
a97cd2d0cc Fix #2337.
[SVN r48833]
2008-09-17 22:21:56 +00:00
Peter Dimov
e3b9389a24 Fix #2338.
[SVN r48832]
2008-09-17 22:17:29 +00:00
Peter Dimov
6ba78f76f6 Merge 47736 from trunk (untabify).
[SVN r47739]
2008-07-23 20:47:47 +00:00
Peter Dimov
8c7954a53a Untabify.
[SVN r47736]
2008-07-23 20:04:52 +00:00
Peter Dimov
556b9fe563 Merge 47357 (atomic access N2674 edits) from trunk to release.
[SVN r47358]
2008-07-12 16:18:05 +00:00
Peter Dimov
77ab953171 Updated atomic access syntax to match N2674 and the WD.
[SVN r47357]
2008-07-12 16:07:20 +00:00
Peter Dimov
991b02b03e Whitespace fix.
[SVN r47356]
2008-07-12 15:16:31 +00:00
Peter Dimov
31d0c48f18 Merged 45224, 45225 from trunk to release.
[SVN r47355]
2008-07-12 14:47:13 +00:00
Peter Dimov
1b49f08cb8 Merged 44686 from trunk to release.
[SVN r47350]
2008-07-12 12:21:19 +00:00
Peter Dimov
034c12d244 Merged 44636, 44640, 45094 (atomic access) from trunk to release.
[SVN r47349]
2008-07-12 11:57:45 +00:00
Peter Dimov
f884c53bd6 Updated spinlock_pool.hpp from trunk HEAD; takes care of 45069.
[SVN r47346]
2008-07-12 11:41:20 +00:00
Peter Dimov
07b4c17980 Merged 44979, 45068, 45085, 45089, 45177, 45194, 45346, 45422, 45545, 46055 from trunk to release
[SVN r47345]
2008-07-12 11:37:16 +00:00
Peter Dimov
1bc4f16ff8 Update esft_regtest.cpp to trunk HEAD; takes care of 43829, 43856, 44775.
[SVN r47342]
2008-07-12 10:45:56 +00:00
Peter Dimov
774a8d330c Merged 44595, 44638, 44707, 44711, 44728 from trunk to release
[SVN r47341]
2008-07-12 10:41:24 +00:00
Peter Dimov
0fd94d6d56 Updated sp_counted_base.hpp to trunk version; takes care of 44369, 44441.
[SVN r47340]
2008-07-12 10:17:08 +00:00
Peter Dimov
866590ee97 Merged 43316, 43317, 43318, 43733, 43782, 43873, 43888, 43916, 43950, 44055, 44056, 44058, 44073, 44074, 44132, 44137, 44138, 44140, 44344 from trunk to release
[SVN r47339]
2008-07-12 09:55:08 +00:00
Peter Dimov
2a92df56f2 #include <ia64intrin.h> in spinlock_sync.hpp as well.
[SVN r46055]
2008-06-02 20:01:30 +00:00
Peter Dimov
a9cd84f43d Fix #1938 in release
[SVN r45691]
2008-05-23 20:30:15 +00:00
Peter Dimov
366472fc35 Fix #1938 in trunk
[SVN r45690]
2008-05-23 20:29:14 +00:00
Peter Dimov
2bfe13c9c4 Renamed CRITICAL_SECTION to critical_section to avoid ambiguity.
[SVN r45545]
2008-05-19 15:09:54 +00:00
John Maddock
83e2510ce5 Use the "no_tr1" version of <functional>: addition of Boost.Exception support to throw_exception has created new cyclic dependencies with Boost.TR1.
[SVN r45422]
2008-05-16 11:12:32 +00:00
Peter Dimov
31685fe551 Updated Borland workaround to properly use BOOST_NO_MEMBER_TEMPLATE_FRIENDS.
[SVN r45347]
2008-05-14 00:21:28 +00:00
Peter Dimov
05e050abe0 Disable sp_convertible for Borland 5.x.
[SVN r45346]
2008-05-13 23:53:12 +00:00
Ion Gaztañaga
d261079616 Replaced non-ascii characters, ticket 1736
[SVN r45225]
2008-05-08 19:22:16 +00:00
Ion Gaztañaga
d52878df88 Replaced non-ascii characters, ticket 1736
[SVN r45224]
2008-05-08 19:08:38 +00:00
Peter Dimov
4b0490c0ae Fix sp_convertible_test.cpp failure in C++0x mode.
[SVN r45194]
2008-05-07 10:15:16 +00:00
Peter Dimov
2f1b1acc7a Fix g++ 3.2 regression.
[SVN r45177]
2008-05-06 18:58:15 +00:00
Peter Dimov
f0f9f72be6 sp_atomic_mt2_test.cpp added.
[SVN r45094]
2008-05-03 22:47:35 +00:00
Peter Dimov
efdc390bc9 intrusive_ptr::reset() added.
[SVN r45089]
2008-05-03 20:12:25 +00:00
Peter Dimov
d13f1d8694 More fixes for MSVC 6.0.
[SVN r45086]
2008-05-03 19:43:52 +00:00
Peter Dimov
83c43617af Fixes for MSVC 6.0.
[SVN r45085]
2008-05-03 19:29:01 +00:00
Peter Dimov
da323af72d Fixes for old compilers.
[SVN r45069]
2008-05-03 15:33:06 +00:00
Peter Dimov
0c4aaef77c Fix #1106.
[SVN r45068]
2008-05-03 15:07:58 +00:00
Ralf W. Grosse-Kunstleve
440fcb7ba0 missing workaround.hpp include added
[SVN r45040]
2008-05-02 19:44:56 +00:00
Peter Dimov
18a6c1add8 make_shared added; tweaks for old compilers; fixes #1884.
[SVN r44979]
2008-05-01 16:50:39 +00:00
Daniel Frey
357d3c4d54 Fixed comment to reflect the intention and the current code
[SVN r44873]
2008-04-29 05:32:13 +00:00
Anthony Williams
4bb747fb27 reverted accidental change
[SVN r44839]
2008-04-28 09:04:40 +00:00
Anthony Williams
f13591ef2b Added detail::try_lock_wrapper for use as scoped_try_lock typedefs, to fix issue #1873
[SVN r44838]
2008-04-28 09:00:58 +00:00
Daniel Frey
e3422efec6 Improved sp_deleter_wrapper implementation
[SVN r44837]
2008-04-28 07:17:11 +00:00
Daniel Frey
a01e4c3f83 Refactored and optimized enable_shared_from_this
[SVN r44782]
2008-04-26 19:59:11 +00:00
Daniel Frey
6f8dc5923c Added new reset()-counterparts for the new ctors
[SVN r44777]
2008-04-26 15:42:13 +00:00
Peter Dimov
7dc6b3d810 Added a few more tests.
[SVN r44775]
2008-04-26 13:39:52 +00:00
Daniel Frey
2251b1d2df No need for the new ctors to be templates
[SVN r44772]
2008-04-26 06:36:59 +00:00
Daniel Frey
8b3907ae81 Remove dynamic_cast in init_internal_shared_once()
[SVN r44744]
2008-04-23 19:32:44 +00:00
Daniel Frey
77f2d3f614 Reduce enable_shared_from_this overhead (replace _internal_shared_ptr by _internal_shared_count)
[SVN r44730]
2008-04-23 06:12:39 +00:00
Peter Dimov
93545d5cf2 Silence an g++ -Wextra warning.
[SVN r44728]
2008-04-23 00:33:58 +00:00
Daniel Frey
9e92c6354c Reduce enable_shared_from_this overhead
[SVN r44724]
2008-04-22 19:48:39 +00:00
Daniel Frey
e12ed6864b Avoid unneccessary increment/decrement of reference count
[SVN r44711]
2008-04-22 06:31:32 +00:00
Peter Dimov
b541145a60 Honor BOOST_NO_TEMPLATED_IOSTREAMS.
[SVN r44707]
2008-04-21 23:01:51 +00:00
Jürgen Hunold
ca344809ba Remove trailing comma at end of enumerator list (gcc 4.x -pedantic error)
[SVN r44686]
2008-04-21 08:07:55 +00:00
Peter Dimov
7802c695ef sp_atomic_mt_test.cpp added.
[SVN r44640]
2008-04-20 17:00:58 +00:00
Peter Dimov
71fa2cd658 Factored out boost/detail/lightweight_thread.hpp.
[SVN r44638]
2008-04-20 15:37:08 +00:00
Peter Dimov
04be979670 Atomic access added.
[SVN r44636]
2008-04-20 14:59:12 +00:00
John Maddock
35f2af947c Changed #includes to avoid circular dependencies between shared_ptr and TR1.
[SVN r44595]
2008-04-19 16:28:00 +00:00
Frank Mori Hess
3a578ac7c1 Added another BOOST_ASSERT to enable_shared_from_this::_internal_accept_owner.
[SVN r44499]
2008-04-17 13:40:44 +00:00
Frank Mori Hess
9365853fde Avoid needless overhead of wrapping owner's deleter in deleter_wrapper if
shared_from_this has not been called yet, as Peter suggested
earlier.



[SVN r44448]
2008-04-16 00:06:29 +00:00
Peter Dimov
16828c9c0a Disabled sync use for hppa.
[SVN r44441]
2008-04-15 19:02:13 +00:00
Peter Dimov
2fe899cdfe Disable sync use for arm and hppa.
[SVN r44440]
2008-04-15 18:57:46 +00:00
Peter Dimov
b45d011d5a Honor BOOST_DISABLE_THREADS; route GCC/ARM to the spinlock implementation; fall back to the spinlock implementation instead of using pthread_mutex.
[SVN r44369]
2008-04-13 15:35:40 +00:00
Peter Dimov
4094c23537 sp_accept_owner added.
[SVN r44353]
2008-04-12 18:22:18 +00:00
Peter Dimov
f85a1bf406 shared_ptr::lock no longer requires exceptions.
[SVN r44344]
2008-04-12 14:27:22 +00:00
Peter Dimov
dbd62686a3 ARM assembly fix.
[SVN r44140]
2008-04-09 23:19:22 +00:00
Peter Dimov
e4f638025c spinlock_gcc_arm.hpp added.
[SVN r44138]
2008-04-09 21:08:39 +00:00
Peter Dimov
d8296b3933 sp_counted_base_spin.hpp added, enabled by BOOST_SP_USE_SPINLOCK.
[SVN r44137]
2008-04-09 19:58:54 +00:00
Peter Dimov
b4885a1dd6 Proper try_lock semantics.
[SVN r44132]
2008-04-09 17:49:20 +00:00
Peter Dimov
748b1baee8 detail/spinlock_pool.hpp added.
[SVN r44074]
2008-04-06 16:53:11 +00:00
Peter Dimov
4880292c07 Add MT runs of yield_k_test and spinlock_try_test.
[SVN r44073]
2008-04-06 16:23:42 +00:00
Peter Dimov
6b25c57712 BOOST_COMPILER_FENCE factored out.
[SVN r44058]
2008-04-05 16:32:49 +00:00
Peter Dimov
373c52efa3 BOOST_SMT_PAUSE factored out.
[SVN r44056]
2008-04-05 15:23:28 +00:00
Peter Dimov
acb6824ef7 spinlock_nt.hpp added, Cygwin fixes.
[SVN r44055]
2008-04-05 15:06:31 +00:00
Peter Dimov
316d00c3fc Fix #1759 in release.
[SVN r44005]
2008-04-02 21:52:08 +00:00
Peter Dimov
515be965bd Fix #1759 in trunk.
[SVN r44004]
2008-04-02 21:42:52 +00:00
Peter Dimov
6ef32e1627 boost::detail::spinlock added.
[SVN r43950]
2008-03-30 16:33:58 +00:00
Peter Dimov
2452705117 Missing "inline" added.
[SVN r43916]
2008-03-28 20:44:45 +00:00
Peter Dimov
bb076d67e6 detail::yield(k) added.
[SVN r43888]
2008-03-27 22:20:11 +00:00
Peter Dimov
b08789b784 Silence unused parameter warning.
[SVN r43887]
2008-03-27 22:13:55 +00:00
Peter Dimov
5df69a8946 Added "Throws: nothing" to get_deleter.
[SVN r43873]
2008-03-26 18:34:29 +00:00
Peter Dimov
dc6a8f0696 _internal_accept_owner now checks if _owned isn't already true.
[SVN r43856]
2008-03-25 15:46:40 +00:00
Peter Dimov
af7d4fabad New enable_shared_from_this tests, fix.
[SVN r43829]
2008-03-24 16:00:28 +00:00
Frank Mori Hess
d17a096407 Fixed compile error with new enable_shared_from_this code,
reported by Tim Blechmann 


[SVN r43823]
2008-03-24 15:07:00 +00:00
Frank Mori Hess
d7448b5746 Added a little more test code for new enable_shared_from_this behavior.
[SVN r43804]
2008-03-23 14:51:40 +00:00
Frank Mori Hess
f22516d650 Fixed bogus test failure caused by new enable_shared_from_this features.
[SVN r43782]
2008-03-21 21:12:21 +00:00
Frank Mori Hess
b30aa1468a Worked around compilation error in boost::get_deleter when using old versions
of g++.



[SVN r43766]
2008-03-21 19:19:25 +00:00
Peter Dimov
5b17f88f0e Initialize _owned in the copy constructor as well.
[SVN r43739]
2008-03-20 22:10:52 +00:00
Frank Mori Hess
1c2d780f9e Added support for calling enable_shared_from_this::shared_from_this in
constructors.  Closes #1696.



[SVN r43738]
2008-03-20 19:32:43 +00:00
Peter Dimov
2eb3991630 Regression test for enable_shared_from_this.
[SVN r43733]
2008-03-19 19:39:50 +00:00
Peter Dimov
3a4dc43924 Fix #398, as long as the macros BOOST_NO_STD_TYPEINFO and BOOST_NO_IOSTREAM are defined. I don't know how Boost.Config needs to be changed to autodetect eVC4 and set these on its own.
[SVN r43318]
2008-02-19 14:26:36 +00:00
Peter Dimov
a055d9829e Fixes #1444.
[SVN r43317]
2008-02-19 14:01:13 +00:00
Peter Dimov
f596092bac Fixes #1590.
[SVN r43316]
2008-02-19 13:18:58 +00:00
Daniel James
4ba016d29e Merged revisions 43206,43208-43213 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r43206 | danieljames | 2008-02-10 09:55:03 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Fix some broken links.
........
  r43209 | danieljames | 2008-02-10 14:56:22 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Link to people pages on the website, as they've been removed from the download.
........
  r43210 | danieljames | 2008-02-10 15:02:17 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Point links to the pages that used to be in 'more' to the site.
........
  r43212 | danieljames | 2008-02-10 16:10:16 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Fix links on the home page as well.
........
  r43213 | danieljames | 2008-02-10 16:21:22 +0000 (Sun, 10 Feb 2008) | 1 line
  
  Generated documentation which is no longer generated.
........


[SVN r43214]
2008-02-10 16:39:38 +00:00
Daniel James
7ca6d86bdc Point links to the pages that used to be in 'more' to the site.
[SVN r43210]
2008-02-10 15:02:17 +00:00
Daniel James
b2a3c9e59d Link to people pages on the website, as they've been removed from the download.
[SVN r43209]
2008-02-10 14:56:22 +00:00
Beman Dawes
60ae24f4ae Pick up missing smart_ptr, utility, and type_traits files from full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41386]
2007-11-25 22:34:55 +00:00
Beman Dawes
dba6ebbb01 Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41370]
2007-11-25 18:38:02 +00:00
Beman Dawes
d2194e3b24 Full merge from trunk at revision 41356 of entire boost-root tree.
[SVN r41369]
2007-11-25 18:07:19 +00:00
Beman Dawes
5ab6b24856 config, detail, filesystem, system, tools, at 41278.
[SVN r41316]
2007-11-23 17:03:14 +00:00
Peter Dimov
e6f6ec9fa3 Attempt unspecified bool fix for Sun 5.7-5.9
[SVN r40914]
2007-11-07 22:47:55 +00:00
Peter Dimov
f854829d86 Port unspecified_bool fix for Sun 5.8 from RC_1_34
[SVN r40708]
2007-11-02 23:46:04 +00:00
Boris Gubenko
7b5beeedde fix typo in comment
[SVN r40605]
2007-10-30 12:58:36 +00:00
Boris Gubenko
9e41d1f194 add support for aC++ on HP-UX ia64
[SVN r40604]
2007-10-30 12:48:44 +00:00
Boris Gubenko
f49a2fb1e1 add support for aC++ on HP-UX ia64
[SVN r40603]
2007-10-30 12:43:47 +00:00
Beman Dawes
87c6b6b403 Starting point for releases
[SVN r39706]
2007-10-05 14:25:06 +00:00
Peter Dimov
9db307eda5 defined(__ppc) added (Daniel P Furlani)
[SVN r39427]
2007-09-20 20:46:56 +00:00
Peter Dimov
5a85c1f0f2 CINT support (Nils Krumnack)
[SVN r39282]
2007-09-14 19:19:09 +00:00
Peter Dimov
f5ce4dbc4c Fixes #1243
[SVN r39199]
2007-09-11 20:58:19 +00:00
Peter Dimov
b2354d0a5e BOOST_NO_TYPEID support (#1108).
[SVN r38977]
2007-08-26 20:35:52 +00:00
Peter Dimov
e0ca42bb88 BOOST_NO_TYPEID support (#1108).
[SVN r38976]
2007-08-26 20:34:40 +00:00
Peter Dimov
bca336bf35 Updated the unspecified_bool_type to match shared_ptr.
[SVN r38975]
2007-08-26 19:42:50 +00:00
Vladimir Prus
6646d8acd2 Remove V1 Jamfiles
[SVN r38516]
2007-08-08 19:02:26 +00:00
nobody
c66f0aeecc This commit was manufactured by cvs2svn to create tag
'Version_1_34_1'.

[SVN r38286]
2007-07-24 19:28:14 +00:00
Peter Dimov
ecb41cb150 sp_unary_addr_test added (reported by Scott French)
[SVN r38137]
2007-07-04 16:35:44 +00:00
Peter Dimov
ed8db8b5f2 Switched to BSL, Darin Adler has given blanket permission
[SVN r37917]
2007-06-06 16:39:52 +00:00
Peter Dimov
4ba37fce95 Negative test for conversion to void*
[SVN r37756]
2007-05-23 23:22:45 +00:00
Eric Niebler
94db735438 gcc-4.2+ moved atomicity.hpp from bits/ to ext/
[SVN r37728]
2007-05-21 01:34:43 +00:00
Peter Dimov
5b57eff9b8 atomic_count_gcc_x86 added since _sync doesn't work on i386
[SVN r37637]
2007-05-08 20:14:38 +00:00
Peter Dimov
f980da560a Use __sync intrinsics on g++ 4.1+
[SVN r37528]
2007-04-28 18:13:12 +00:00
Peter Dimov
ffba68221b Use __sync intrinsics on g++ 4.1+
[SVN r37527]
2007-04-28 16:15:13 +00:00
Peter Dimov
4d45e5b9b5 Move tests added
[SVN r37526]
2007-04-28 15:49:13 +00:00
Peter Dimov
86d3f0aba7 Changed move constructors/assignments to leave the source empty
[SVN r37439]
2007-04-15 02:47:45 +00:00
Peter Dimov
66a25bd4a9 Move support
[SVN r37434]
2007-04-13 22:04:22 +00:00
Peter Dimov
745dbedbaa Fix CW regression re strcmp, strcpy
[SVN r37407]
2007-04-09 22:24:37 +00:00
Peter Dimov
26f83e75ef intrusive_ptr::reset added
[SVN r37406]
2007-04-09 21:35:07 +00:00
Peter Dimov
ce72827dc7 Aliasing support
[SVN r37405]
2007-04-09 18:48:47 +00:00
Peter Dimov
6e8f075d42 make_shared removed
[SVN r37404]
2007-04-09 18:42:49 +00:00
Peter Dimov
ae6c180be8 _MANAGED fix for sp_enable_shared_from_this
[SVN r37403]
2007-04-09 16:37:30 +00:00
Peter Dimov
54e12d03fd Aliasing constructor added
[SVN r37402]
2007-04-09 16:32:45 +00:00
Peter Dimov
469578e976 Fix C++0x ambiguity between boost::shared_ptr and std::shared_ptr
[SVN r37374]
2007-04-06 00:23:17 +00:00
Peter Dimov
97118668e2 Fix compare_fail failure
[SVN r37373]
2007-04-06 00:21:41 +00:00
Peter Dimov
1c3813ce52 BOOST_ASSERTs added (SF patch 1612733 by 'Baraclese')
[SVN r36316]
2006-12-10 21:01:55 +00:00
Peter Dimov
b440e85452 Fixed get_deleter comment
[SVN r36229]
2006-12-01 14:24:58 +00:00
Peter Dimov
d889751bc0 License/copyright edits
[SVN r35957]
2006-11-09 20:24:23 +00:00
Peter Dimov
0609322489 License/copyright edits
[SVN r35957]
2006-11-09 20:24:23 +00:00
Peter Dimov
b215e34650 License/copyright edits
[SVN r35956]
2006-11-09 20:17:14 +00:00
Peter Dimov
2f70e81b73 TR1 conformance fix
[SVN r35949]
2006-11-09 12:21:28 +00:00
Peter Dimov
6284a1abef TR1 conformance fix
[SVN r35948]
2006-11-09 12:15:23 +00:00
Beman Dawes
c464a07ab1 Merged copyright and license addition
[SVN r35907]
2006-11-07 19:27:00 +00:00
Beman Dawes
41d4167533 Add copyright, license
[SVN r35905]
2006-11-07 19:11:57 +00:00
Peter Dimov
4a98c2931c Patch #1551992 (Michael Fink)
[SVN r35882]
2006-11-06 17:25:59 +00:00
Peter Dimov
75bc821afd Patch #1551992 (Michael Fink)
[SVN r35882]
2006-11-06 17:25:59 +00:00
Rene Rivera
ebc0af9147 Remove obsolete Boost.Build v1 files.
[SVN r35880]
2006-11-06 17:10:46 +00:00
Peter Dimov
db0969d97b TR1 cyclic inclusion fix
[SVN r34512]
2006-07-12 12:31:28 +00:00
Peter Dimov
39551bdc1a A negative test for p > q added.
[SVN r34509]
2006-07-11 23:17:17 +00:00
Peter Dimov
6412de1dd5 TR1 cyclic dependency fixes.
[SVN r34499]
2006-07-10 13:17:41 +00:00
Peter Dimov
8d2f7fc5ef g++/SPARC version by Piotr Wyderski, thanks to Tomas Puverle and Michael van der Westhuizen
[SVN r34480]
2006-07-08 17:44:55 +00:00
Peter Dimov
7c477960d3 Second try, revert to old Sun behavior for 5.8 and below
[SVN r34479]
2006-07-07 22:48:20 +00:00
Peter Dimov
7e5d7011e6 Attempt to fix sun-5.8 shared_ptr_delete_fail regression
[SVN r34466]
2006-07-06 12:13:25 +00:00
Peter Dimov
ffd73c39b3 Solaris implementation by Michael van der Westhuizen
[SVN r34450]
2006-07-03 10:02:46 +00:00
Peter Dimov
4fcee64483 New, improved and more portable unspecified bool type. I hope.
[SVN r33987]
2006-05-17 22:39:34 +00:00
Peter Dimov
75cd88112c Workaround for MSVC 8.0 managed/unmanaged mismatch (reported by Loic Joly)
[SVN r33968]
2006-05-15 13:56:27 +00:00
Peter Dimov
203764eb51 Fix VC6 codegen issue (Alain Cormier)
[SVN r33747]
2006-04-19 21:03:18 +00:00
Peter Dimov
6e120f4bf1 Fix VC6 codegen issue (Alain Cormier)
[SVN r33747]
2006-04-19 21:03:18 +00:00
Peter Dimov
747c9a1d3e Rvalue auto_ptr constructor is no longer explicit.
[SVN r33526]
2006-03-29 19:19:14 +00:00
Peter Dimov
7ce5b55f5c Fix issues on HP-UX (ILP32 model)
[SVN r33464]
2006-03-24 00:38:22 +00:00
Peter Dimov
e38d0daaab Fix issues on HP-UX (ILP32 model)
[SVN r33449]
2006-03-22 22:46:53 +00:00
nobody
f3e94d8ca0 This commit was manufactured by cvs2svn to create branch 'RC_1_34_0'.
[SVN r33417]
2006-03-21 02:26:31 +00:00
Peter Dimov
c36e023162 Documented the allocator support
[SVN r33393]
2006-03-19 19:52:00 +00:00
Peter Dimov
00f744bf1e Minor rewording.
[SVN r33367]
2006-03-18 14:58:20 +00:00
Peter Dimov
24d1e6f8dd Added 'm'(*pw) inputs (thanks to Howard Hinnant)
[SVN r33364]
2006-03-18 01:48:21 +00:00
Peter Dimov
ae0a48d544 Removed erroneous // never throws annotations (reported by Scott Meyers)
[SVN r33241]
2006-03-06 23:06:10 +00:00
Peter Dimov
e427716dc2 Fully qualified detail:: to work around a subtle VC 7.1 problem.
[SVN r32994]
2006-02-18 19:17:33 +00:00
Peter Dimov
8c256502cc Added a test for rvalue auto_ptrs
[SVN r32327]
2006-01-15 13:55:37 +00:00
Peter Dimov
a86b2f7fbf Rvalue auto_ptr support, technique by Dave Abrahams
[SVN r32326]
2006-01-15 13:54:53 +00:00
Peter Dimov
a196f39cd0 Added documentation for pointer_to_other.hpp.
[SVN r31941]
2005-12-06 23:17:32 +00:00
Peter Dimov
90b5a3736a Pointer utilities added (proposed by Ion Gaztañaga)
[SVN r31932]
2005-12-06 13:26:13 +00:00
Peter Dimov
2d25f8f036 Qualified ptrdiff_t with std:: (fixes a failure on CW 9.4)
[SVN r31790]
2005-11-27 17:16:30 +00:00
Peter Dimov
3771707bb7 Added a test for the custom allocator constructor/reset.
[SVN r31624]
2005-11-11 21:07:18 +00:00
Peter Dimov
239bb6d966 #include reorderings for Boost.TR1
[SVN r31623]
2005-11-11 21:06:08 +00:00
Peter Dimov
25ca855127 shared_ptr( p, d, a ) added.
[SVN r31613]
2005-11-09 20:05:42 +00:00
Peter Dimov
0127c06692 Added a note that it's not necessary to initialize _internal_weak_this.
[SVN r31566]
2005-11-05 14:40:29 +00:00
Peter Dimov
9edd3beebc Added a note that it's not necessary to initialize _internal_weak_this.
[SVN r31565]
2005-11-05 14:33:42 +00:00
Peter Dimov
92a027fbeb Minor warning fix for SGI MIPSPro (Kevin Wheatley)
[SVN r31113]
2005-09-25 22:00:31 +00:00
Peter Dimov
7880720bc1 Made the Boost logo link to the home page
[SVN r31112]
2005-09-25 21:54:19 +00:00
Peter Dimov
235994873f Documented conversion to 'unspecified bool'
[SVN r31111]
2005-09-25 21:49:08 +00:00
Peter Dimov
7bfddbccf6 Comparison operators against a raw pointer now accept different types
[SVN r31110]
2005-09-25 21:27:00 +00:00
Douglas Gregor
c6a4e93a05 Qualify detail references
[SVN r30824]
2005-09-06 03:28:01 +00:00
John Maddock
ff7e027648 Large patch from Ulrich Eckhardt to fix support for EVC++ 4.
[SVN r30670]
2005-08-25 16:27:28 +00:00
Peter Dimov
08f517b5b0 Switched to 'int' because 'long' is 64 bits on PPC64
[SVN r30641]
2005-08-23 21:32:42 +00:00
Peter Dimov
6b3f961542 Removed explicit register use (thanks to Howard Hinnant)
[SVN r30585]
2005-08-15 19:44:15 +00:00
Douglas Gregor
0db2a88403 Merged from 1.33.0 release
[SVN r30540]
2005-08-12 13:02:37 +00:00
Peter Dimov
afc17037de Another minor documentation fix.
[SVN r30224]
2005-07-22 23:40:53 +00:00
Peter Dimov
0cee41d47e Minor documentation fix.
[SVN r30190]
2005-07-21 00:51:38 +00:00
Peter Dimov
eb3d3464db operator< documenation fix.
[SVN r30166]
2005-07-18 20:33:59 +00:00
Peter Dimov
8d2aeea3a8 Moved warning 8027 suppression above the #includes
[SVN r29852]
2005-06-30 21:49:40 +00:00
Peter Dimov
675d09723a Lock-free implementation documented, minor changes to align with TR1
[SVN r29536]
2005-06-12 12:58:17 +00:00
Joaquín M. López Muñoz
24c23b8064 disabled asm implementation for ICC/IA64
[SVN r29166]
2005-05-24 12:11:35 +00:00
Peter Dimov
880c2e1062 Detabified.
[SVN r29039]
2005-05-18 20:10:01 +00:00
Peter Dimov
357f57d147 Added a weak_ptr timing test.
[SVN r28483]
2005-04-26 11:08:28 +00:00
Rene Rivera
8bacee46eb Add x86 assembly implementation for use with CodeWarrior. Commented out initially until we can get more widespread testing for verification of performance improvements (if any).
[SVN r28422]
2005-04-22 16:36:38 +00:00
Ben Hutchings
4e4ec29fc9 Added an implementation of sp_counted_base for g++/ia64.
[SVN r28325]
2005-04-19 17:43:48 +00:00
Rene Rivera
df1d8b27df Make assembly functions inline to prevent multiple definitions. Required to change from function level assembly to regular functions with statement level assembly.
[SVN r28133]
2005-04-11 15:59:44 +00:00
Peter Dimov
76722e125f Clear reservation for 970 (thanks to Miro Jurisic and Philip Koch)
[SVN r28060]
2005-04-08 10:39:28 +00:00
Peter Dimov
d24f6d3b97 Remove hardcoded ebx
[SVN r28017]
2005-04-06 14:12:40 +00:00
Peter Dimov
6ab6b66601 One more long -> int fix
[SVN r28016]
2005-04-06 13:40:34 +00:00
Peter Dimov
559056c856 x86-64 fixes: long -> int, lea -> mov+inc
[SVN r28015]
2005-04-06 13:34:41 +00:00
Peter Dimov
13c128f98f Enabled PPC versions
[SVN r28007]
2005-04-06 08:15:48 +00:00
Rene Rivera
3ebc9b8f0b Remove extra argument to atomic_dcrement.
[SVN r27994]
2005-04-06 00:32:09 +00:00
Peter Dimov
361a7c3fd0 PowerPC dispatch added, disabled for now.
[SVN r27988]
2005-04-05 20:39:56 +00:00
Peter Dimov
faa675ad6a PowerPC implementations added.
[SVN r27986]
2005-04-05 20:29:15 +00:00
Peter Dimov
319836fe78 Constraints fixed (again), volatile/memory clobber removed from conditional_inc
[SVN r27983]
2005-04-05 16:04:36 +00:00
Peter Dimov
d0656015ad Fixed 'eax' to '%eax' in clobber; enabled gcc/x86 version
[SVN r27965]
2005-04-04 22:43:03 +00:00
Peter Dimov
f1a9148a43 Constraints fixed for g++ 3.4, atomic_increment added
[SVN r27958]
2005-04-04 19:36:18 +00:00
Peter Dimov
1942b64751 weak_ptr_mt_test.cpp added.
[SVN r27938]
2005-04-02 19:35:58 +00:00
Peter Dimov
a0eb5daf75 Mark eax as earlyclobber
[SVN r27937]
2005-04-02 18:56:38 +00:00
Peter Dimov
6046a099ba Added an implementation of sp_counted_base for g++/x86
[SVN r27933]
2005-04-02 17:14:26 +00:00
Peter Dimov
e0ee037e2d Spinlocks removed.
[SVN r27932]
2005-04-02 13:12:28 +00:00
Peter Dimov
13657c8bda lw_mutex_test added.
[SVN r27931]
2005-04-02 12:51:17 +00:00
Peter Dimov
52587aaa05 Fixed shared_ptr_delete_fail failure on g++ 3.3 and below
[SVN r27930]
2005-04-02 12:00:14 +00:00
Peter Dimov
0669d41076 Atomics are in namespace __gnu_cxx for g++ 3.4+
[SVN r27929]
2005-04-02 11:37:53 +00:00
Peter Dimov
8f2beee8e9 Link fixed.
[SVN r27906]
2005-04-01 19:33:00 +00:00
Peter Dimov
3adfc7842c Kill *_linux variants of atomic_count and lightweight_mutex.
[SVN r27889]
2005-03-30 22:52:54 +00:00
Peter Dimov
613e684b30 shared_ptr_delete_fail.cpp added (reported by Dan Bikel)
[SVN r27888]
2005-03-30 22:06:25 +00:00
Peter Dimov
bfc0225cda Switched to atomic_count
[SVN r27811]
2005-03-24 21:55:24 +00:00
Peter Dimov
a67e505cf5 Made use of detail/interlocked.hpp
[SVN r27810]
2005-03-24 21:29:29 +00:00
Peter Dimov
adec862262 atomic_count_test.cpp added.
[SVN r27746]
2005-03-20 15:40:30 +00:00
Peter Dimov
c6bf857f8b Made the pthread mutex mutable
[SVN r27740]
2005-03-18 21:27:22 +00:00
Peter Dimov
14024e2598 Add a comment thanking Ben Hutchings for the #w+(#s!=0) formulation
[SVN r27735]
2005-03-18 13:04:43 +00:00
Peter Dimov
34953d8a45 Split sp_counted_base into no threads (nt), win32 lock-free (w32) and pthreads (pt)
[SVN r27729]
2005-03-18 01:27:11 +00:00
Peter Dimov
09a0ba8c75 sp_counted_impl_p added for the pointer constructor
[SVN r27727]
2005-03-17 23:30:47 +00:00
Peter Dimov
b0eb65b433 Refactored sp_counted_impl.hpp out of shared_count.hpp
[SVN r27726]
2005-03-17 23:05:26 +00:00
Peter Dimov
c830315dff Refactored shared_count.hpp into bad_weak_ptr.hpp, sp_counted_base.hpp
[SVN r27725]
2005-03-17 22:45:11 +00:00
Peter Dimov
b07447aa6e BCB 6.4 still needs option -pc (reported by Pavel Vozenilek)
[SVN r27672]
2005-03-15 16:02:01 +00:00
Peter Dimov
42a739b357 Fixed nonportable elision assumption.
[SVN r27093]
2005-02-04 16:39:44 +00:00
Peter Dimov
7d59d29ad1 HP aCC fix for get_deleter (Jaroslav Gresula)
[SVN r27092]
2005-02-04 16:28:50 +00:00
Peter Dimov
5616a1a872 Added note on BOOST_MEM_FN_ENABLE_STDCALL.
[SVN r26687]
2005-01-13 13:45:59 +00:00
Aleksey Gurtovoy
e5c1e12a66 merge RC_1_32_0 fixes
[SVN r26333]
2004-11-28 04:44:21 +00:00
Peter Dimov
8f317492ee Outdated comment removed (Jonathan Wakely)
[SVN r26272]
2004-11-22 12:32:35 +00:00
Aleksey Gurtovoy
c81be1e2e7 c++boost.gif -> boost.png replacement
[SVN r25573]
2004-10-05 15:45:52 +00:00
John Maddock
1bc58ea861 Updated to use the BSL (using permissions supplied in more/blanket-permission.txt)
[SVN r24804]
2004-08-29 10:29:46 +00:00
Peter Dimov
27be736b8f Fixed sp_enable_shared_from_this to not use void cv * since this breaks function types.
[SVN r24718]
2004-08-24 16:27:31 +00:00
Douglas Gregor
ef51f6a1de License update
[SVN r24598]
2004-08-19 15:23:47 +00:00
Douglas Gregor
6b00a55542 License updates
[SVN r24597]
2004-08-19 15:19:17 +00:00
John Maddock
858cefbfe8 Removed boost.org copyright assignments, and reverted to orginal author (as based on cvs history).
[SVN r24402]
2004-08-11 10:59:33 +00:00
John Maddock
c7abff0099 Updated Beman Dawes' licence statement to use the new prefered form of words.
[SVN r24370]
2004-08-10 10:34:20 +00:00
Douglas Gregor
cb6cb636f7 Converted to Boost Software License, Version 1.0
[SVN r24055]
2004-07-26 00:32:12 +00:00
John Maddock
366d2666d4 Licence update
[SVN r24031]
2004-07-25 12:01:00 +00:00
Peter Dimov
9c67a59d43 Fixed lwm_gcc, had the same bug as atomic_count_gcc (Tyson Whitehead)
[SVN r23367]
2004-07-06 10:52:06 +00:00
Peter Dimov
7361e476b8 Fixed operator--
[SVN r23210]
2004-06-27 15:40:29 +00:00
Peter Dimov
e1bd18f6a6 Made value_ mutable to enable operator long() const to compile
[SVN r23208]
2004-06-27 15:09:46 +00:00
Vladimir Prus
1346982b80 Fix a typo
[SVN r23077]
2004-06-10 12:31:20 +00:00
Peter Dimov
c48f05dcb4 enable_shared_from_this is now const-tolerant.
[SVN r22298]
2004-02-16 18:50:07 +00:00
Peter Dimov
53cc52127b Self-assignment optimization
[SVN r22233]
2004-02-10 23:17:12 +00:00
Beman Dawes
7fb399b3bb index.htm renamed index.html
[SVN r21231]
2003-12-11 23:31:15 +00:00
Peter Dimov
93d69af60a _MSC_VER use clarified.
[SVN r20992]
2003-11-28 15:35:21 +00:00
Peter Dimov
09c8685181 Fixed a VC7 'regression' (pointers to volatile cannot be deleted)
[SVN r20977]
2003-11-27 16:58:23 +00:00
Dave Abrahams
15d6b2aace CWPro8 workaround
[SVN r20323]
2003-10-09 14:14:26 +00:00
Dave Abrahams
feff6e40ea Use conforming is_class for EDG compilers
Make is_enum work for class types which are convertible to anything at
all (on many compilers).

smart_ptr library workarounds for __MWERKS__ (must use member function
pointer for unspecified_bool_type).


[SVN r20244]
2003-10-02 17:49:06 +00:00
Peter Dimov
26a93f224e Changed index.htm to redirect to smart_ptr.htm
[SVN r20239]
2003-10-01 11:13:04 +00:00
Peter Dimov
96f572b19b Switched unspecified_bool_type to data member pointer.
[SVN r20238]
2003-10-01 11:12:15 +00:00
Vladimir Prus
d6c4633e89 Add V2 Jamfile
[SVN r20223]
2003-09-30 07:42:34 +00:00
Beman Dawes
106a6d58d4 Change license message to reference Boost Software License
[SVN r20038]
2003-09-12 17:09:29 +00:00
Dave Abrahams
debd953d8f Use the import rule
[SVN r19968]
2003-09-08 17:38:49 +00:00
Peter Dimov
f2c5439644 'volatile' fixes.
[SVN r19961]
2003-09-08 12:26:02 +00:00
Peter Dimov
b4ec0e90fb Switched weak_count_ from #shared+#weak to #weak+(#shared != 0); thanks to Alexander Terekhov and Ben Hutchings
[SVN r19246]
2003-07-21 14:17:03 +00:00
Peter Dimov
2d4eb92401 get_deleter fix for EDG 2.38
[SVN r19148]
2003-07-16 11:54:49 +00:00
Peter Dimov
192970b3b8 const_pointer_cast added.
[SVN r19147]
2003-07-16 11:51:12 +00:00
Peter Dimov
7c36a640ae add_ref split to add_ref_copy and add_ref_lock to eliminate the redundant use_count_ == 0 check.
[SVN r19126]
2003-07-15 12:18:40 +00:00
Peter Dimov
794de98cd1 #include <boost/config.hpp> added.
[SVN r19065]
2003-07-11 17:03:56 +00:00
Peter Dimov
dcdbaf1e57 A binary compatible 'null' lightweight_mutex for Win32 added.
[SVN r18916]
2003-07-02 11:54:40 +00:00
Peter Dimov
6dbec7621d Detect the VC6 STL, not VC6 itself (for Intel)
[SVN r18837]
2003-06-18 16:03:09 +00:00
Peter Dimov
889cb6bee6 -Wundef fixes.
[SVN r18788]
2003-06-12 17:09:24 +00:00
Peter Dimov
11cddbbb45 Minor fix, scoped_ptr in the intro should've been shared_ptr.
[SVN r18745]
2003-06-09 18:25:41 +00:00
Peter Dimov
77c629b6e4 smart_ptr.hpp now includes all smart pointer headers for convenience.
[SVN r18588]
2003-05-28 13:51:35 +00:00
Peter Dimov
d091ee85c0 Turns out Sun CC doesn't like operator int().
[SVN r18512]
2003-05-23 13:46:07 +00:00
Peter Dimov
bc00d5fa1a Fixed bool conversions for Sun 5.3
[SVN r18419]
2003-05-16 12:11:17 +00:00
Peter Dimov
e760759414 Fixed a copy/assignment issue.
[SVN r18122]
2003-03-28 12:27:55 +00:00
Peter Dimov
deab8ca1bb Added link to enable_shared_from_this.html.
[SVN r17397]
2003-02-14 10:55:20 +00:00
Peter Dimov
300f8f7b9a Finished Techniques page, added links to it.
[SVN r17380]
2003-02-13 19:07:20 +00:00
Peter Dimov
d7c841484a Further edits, predestructor technique removed.
[SVN r17374]
2003-02-13 18:35:13 +00:00
Peter Dimov
f4dce1cb88 More prose.
[SVN r17369]
2003-02-13 16:56:07 +00:00
Peter Dimov
b400d34bec Added copyright to Jamfiles.
[SVN r17363]
2003-02-13 15:41:26 +00:00
Peter Dimov
8f0bdd48f8 Minor edits.
[SVN r17335]
2003-02-12 19:11:52 +00:00
Peter Dimov
6d6bcc7be9 Some prose added.
[SVN r17331]
2003-02-12 17:11:29 +00:00
Peter Dimov
851d87a1bb get_shared_ptr renamed to weak_ptr::lock.
[SVN r17307]
2003-02-10 15:56:36 +00:00
Peter Dimov
34f423f811 atomic_count and lightweight_mutex now report an #error on unknown threading configs.
[SVN r17303]
2003-02-10 12:58:50 +00:00
Peter Dimov
190893a1ce BOOST_ENABLE_SP_DEBUG_HOOKS -> BOOST_SP_ENABLE_DEBUG_HOOKS
[SVN r17301]
2003-02-10 12:54:43 +00:00
Peter Dimov
4244992d4d Split winapi.hpp across win32-specific headers, added BOOST_USE_WINDOWS_H option.
[SVN r17277]
2003-02-08 16:05:46 +00:00
Peter Dimov
4b502993b5 Added BOOST_QA_PAGE_SIZE.
[SVN r17270]
2003-02-07 18:43:48 +00:00
Peter Dimov
a24ec3988a Quick_allocator updates.
[SVN r17267]
2003-02-07 15:08:52 +00:00
Peter Dimov
23f7532a9f Disabled some watnings.
[SVN r17255]
2003-02-06 17:16:06 +00:00
Peter Dimov
a790191bc5 Small fixes.
[SVN r17251]
2003-02-06 14:54:15 +00:00
Peter Dimov
86e9a322ba Documentation fixes, make_shared -> get_shared_ptr.
[SVN r17230]
2003-02-05 12:56:48 +00:00
Peter Dimov
98fa979aef Added copyright.
[SVN r17197]
2003-02-04 13:35:06 +00:00
Peter Dimov
be0267f9a3 Enabled copy assignment on all Borland versions (for Kylix) and g++ (for -Wsynth, report by Wolfgang Bangerth)
[SVN r17173]
2003-02-03 13:48:33 +00:00
Dave Abrahams
44afc7e5cd really prevent shared_ptr_alloc_test building from status/.
[SVN r17097]
2003-01-30 20:57:34 +00:00
Dave Abrahams
d2c7febd26 cleanup, add shared_ptr_alloc_test.
[SVN r17095]
2003-01-30 18:20:51 +00:00
Peter Dimov
ddf1f0fdcc Fixed a deadlock in free_unreachable_objects.
[SVN r17090]
2003-01-30 15:06:32 +00:00
Peter Dimov
cd41426fe9 Dave's quick_allocator added, #define BOOST_SP_USE_QUICK_ALLOCATOR to make shared_ptr use it.
[SVN r17087]
2003-01-30 14:20:22 +00:00
Peter Dimov
89ea2156bc intrusive_ptr_test.cpp added.
[SVN r17051]
2003-01-27 14:09:21 +00:00
Peter Dimov
fabd6e5755 Moved 'garbage collector' to sp_collector.cpp, collector_test.cpp added.
[SVN r17050]
2003-01-27 14:02:00 +00:00
Peter Dimov
b60de38d28 Fixed broken links.
[SVN r17044]
2003-01-25 17:58:01 +00:00
Peter Dimov
2dbfc89d4e Removed redundant copy constructor and copy assignment.
[SVN r17043]
2003-01-25 16:51:45 +00:00
Peter Dimov
abb0d9e725 Moved smart_ptr contents to subdirectories, switched to a local test/Jamfile.
[SVN r17042]
2003-01-25 16:17:17 +00:00
Peter Dimov
d030182e87 intrusive_ptr_test added.
[SVN r16993]
2003-01-22 15:22:30 +00:00
Peter Dimov
bd39e2eded intrusive_ptr.html added.
[SVN r16981]
2003-01-21 17:21:24 +00:00
Peter Dimov
d04757128c shared_ptr techniques initial commit
[SVN r16978]
2003-01-21 15:55:59 +00:00
Beman Dawes
868062e81d Add TOC and References sections
[SVN r16912]
2003-01-15 16:35:48 +00:00
Peter Dimov
6bd66fe054 detail::counted_base renamed to sp_counted_base.
[SVN r16900]
2003-01-14 15:13:53 +00:00
Peter Dimov
c5bae28eeb use_count() postconditions added; enable_..._test.cpp renamed.
[SVN r16896]
2003-01-13 18:32:16 +00:00
Peter Dimov
78a47d7619 Algorithm improvements, free_unreachable_objects() added.
[SVN r16894]
2003-01-13 17:11:28 +00:00
Beman Dawes
8eaf187dbd fix bookmarks
[SVN r16827]
2003-01-09 13:37:41 +00:00
Beman Dawes
d36a215554 fix invalid bookmarks
[SVN r16824]
2003-01-09 13:11:10 +00:00
Peter Dimov
8448bbf0b9 Fixes.
[SVN r16795]
2003-01-08 15:01:04 +00:00
Peter Dimov
1dee6e0229 Small optimization.
[SVN r16790]
2003-01-07 23:12:02 +00:00
Peter Dimov
e3f2329c14 report_unreachable_objects() added to sp_debug_hooks.cpp
[SVN r16780]
2003-01-07 15:34:56 +00:00
Peter Dimov
3e616752c9 weak_ptr documentation updated; still a work in progress.
[SVN r16748]
2003-01-04 14:24:14 +00:00
Peter Dimov
987a7d32fb Documentation updated to reflect changes to shared_ptr
[SVN r16739]
2003-01-03 16:53:04 +00:00
Dave Abrahams
fafd9a863b Workarounds for vc6-stlport
[SVN r16706]
2002-12-26 18:23:11 +00:00
Dave Abrahams
51e9783a21 Factor out get_pointer, supply an overload for std::auto_ptr.
[SVN r16672]
2002-12-20 18:15:01 +00:00
Peter Dimov
eee96e8059 Borland 5.6.1 still broken.
[SVN r16666]
2002-12-19 18:15:53 +00:00
Peter Dimov
1ef2a5b059 More weak_ptr tests.
[SVN r16487]
2002-12-03 13:27:35 +00:00
Peter Dimov
c5f7c973d9 Bug in get_deleter fixed.
[SVN r16477]
2002-12-02 14:34:06 +00:00
Peter Dimov
572a97d3c4 Casts renamed.
[SVN r16457]
2002-11-29 14:05:22 +00:00
Peter Dimov
a3d87ff623 Comeau-specific fix.
[SVN r16456]
2002-11-28 13:42:44 +00:00
Peter Dimov
468f63261a weak_ptr_test.cpp added.
[SVN r16427]
2002-11-26 16:01:17 +00:00
Peter Dimov
e60c1f9b49 Some versions of g++ 2.9x don't have basic_ostream.
[SVN r16406]
2002-11-25 13:52:42 +00:00
Peter Dimov
72bcb8ff46 More tests added.
[SVN r16405]
2002-11-25 13:51:56 +00:00
Peter Dimov
12b1871136 operator<< added, as the conversion to 'bool' implicitly defines one anyway.
[SVN r16403]
2002-11-25 12:27:11 +00:00
Peter Dimov
9632464c45 Test w/ NULL pointer to enabled_... object added; bug fixed.
[SVN r16402]
2002-11-25 12:17:56 +00:00
Peter Dimov
1311731e24 Moved the old shared_ptr tests into shared_ptr_basic_test.cpp
[SVN r16401]
2002-11-25 12:12:45 +00:00
Peter Dimov
980307a90a Reintroduced weak_ptr converting constructor; map<weak_ptr<>, ...> is important.
[SVN r16400]
2002-11-25 12:09:13 +00:00
Peter Dimov
1f9908be69 Borland C++ 5.6 still needs the workaround.
[SVN r16379]
2002-11-23 19:18:05 +00:00
Peter Dimov
0aaca2fffe More operator< tests.
[SVN r16377]
2002-11-23 12:59:01 +00:00
Peter Dimov
5dd2c62132 weak_ptr converting constructor removed; operator< can now take different types to aid ownership tests.
[SVN r16376]
2002-11-23 12:47:38 +00:00
Peter Dimov
fadc0716ce get_deleter_test added; associated fixes.
[SVN r16373]
2002-11-22 16:29:51 +00:00
Peter Dimov
ea285b4231 Fixed the previous weak_ptr 'fix'.
[SVN r16370]
2002-11-22 14:41:22 +00:00
Peter Dimov
8d6517484c Stricter tests; associated bug fixes. ;-)
[SVN r16369]
2002-11-22 13:49:54 +00:00
Peter Dimov
66a8e8b3c1 get_deleter<> added.
[SVN r16365]
2002-11-21 14:46:45 +00:00
Peter Dimov
c697e2ef21 Sample implementation of the smart pointer debug hooks.
[SVN r16364]
2002-11-21 13:23:15 +00:00
Peter Dimov
2e53e2e5d7 More tests added.
[SVN r16363]
2002-11-21 13:20:46 +00:00
Peter Dimov
8283ec826b Changed debug hook names, reverted weak_ptr() to have use_count of zero.
[SVN r16362]
2002-11-21 13:14:04 +00:00
Peter Dimov
e32b2adfda Debug hook support, removed self-reset, fixed #%20links.
[SVN r16361]
2002-11-21 13:10:18 +00:00
Peter Dimov
e555d33695 Added array versions of the hooks.
[SVN r16346]
2002-11-20 16:18:13 +00:00
Peter Dimov
de68e6ed1e A missing 'inline' added.
[SVN r16343]
2002-11-20 13:34:18 +00:00
Peter Dimov
804b1483c7 enable_shared_from_this-related fixes.
[SVN r16341]
2002-11-20 12:38:51 +00:00
Peter Dimov
4b200e9847 Borland fix (thanks to Fernando Cacciola)
[SVN r16331]
2002-11-19 18:21:32 +00:00
Peter Dimov
f34866e8a5 License added.
[SVN r16326]
2002-11-19 16:23:01 +00:00
Peter Dimov
45c799f40c Debug hook support moved to shared_count.
[SVN r16325]
2002-11-19 16:18:58 +00:00
Peter Dimov
11a046f628 BOOST_ASSERTs added.
[SVN r16324]
2002-11-19 16:18:18 +00:00
Peter Dimov
b632f1ef20 Debug hooks, general cleanup.
[SVN r16323]
2002-11-19 16:11:21 +00:00
Peter Dimov
7f30268b10 Assignment tests added.
[SVN r16322]
2002-11-19 16:10:38 +00:00
Peter Dimov
7504eff5af A missing Returns clause added.
[SVN r16321]
2002-11-19 16:10:07 +00:00
Peter Dimov
8752c00ebf enable_shared_from_this documentation added.
[SVN r16319]
2002-11-19 14:22:58 +00:00
Peter Dimov
d0c5e83def Test for enable_shared_from_this added.
[SVN r16318]
2002-11-19 13:45:33 +00:00
Peter Dimov
f6b7ff4b34 Major changes to shared_ptr and weak_ptr
[SVN r16314]
2002-11-18 14:37:02 +00:00
Peter Dimov
2314f20c4e element_type added
[SVN r16264]
2002-11-15 19:44:48 +00:00
Peter Dimov
ff7410cad2 Fixed a subtle problem in counted_base::release (report and test case by Per Kristensen)
[SVN r16211]
2002-11-12 13:14:50 +00:00
Peter Dimov
57c0ad44f3 Changed typename to class; some libraries helpfully #define typename
[SVN r15970]
2002-10-23 13:55:18 +00:00
Peter Dimov
ae60bcaffb Small fixes.
[SVN r15951]
2002-10-17 13:23:11 +00:00
Peter Dimov
f2f616a95c BOOST_SP_USE_STD_ALLOCATOR support
[SVN r15807]
2002-10-08 16:37:33 +00:00
Peter Dimov
a8bb455df7 Fixes, notes.
[SVN r15486]
2002-09-23 13:22:38 +00:00
Peter Dimov
9dcbc46225 Minor fix
[SVN r15437]
2002-09-18 13:00:38 +00:00
Peter Dimov
024f918b86 More documentation fixes reflecting Dave Abrahams' comments
[SVN r15411]
2002-09-17 13:59:17 +00:00
Peter Dimov
0f05f41306 Documentation fixes (reflecting Dave Abrahams' comments)
[SVN r15382]
2002-09-16 15:26:52 +00:00
Peter Dimov
4ea6decc7d scoped_ptr::reset changed to copy+swap (problem reported by Thomas Witt)
[SVN r15239]
2002-09-09 17:44:33 +00:00
Peter Dimov
f79b8cb7ae Tabs removed.
[SVN r15175]
2002-09-06 12:50:02 +00:00
Peter Dimov
275cb77378 Fixed broken links.
[SVN r15123]
2002-08-31 13:04:52 +00:00
Peter Dimov
b916445dd8 weak_ptr documentation updates; get() declared deprecated.
[SVN r15111]
2002-08-29 15:18:04 +00:00
Douglas Gregor
c02fee7013 *_ptr.hpp:
- Revert addition of is_pointerlike_helper

weak_ptr.hpp:
  - Revert addition of get_pointer


[SVN r15108]
2002-08-29 13:49:05 +00:00
Douglas Gregor
e77889679f intrusive_ptr.hpp:
scoped_ptr.hpp:
  - include <boost/type_traits/ice.hpp>


[SVN r15104]
2002-08-27 13:33:22 +00:00
Douglas Gregor
b9dceb2340 *_ptr.hpp:
- Added detail::is_pointerlike_helper function templates for Signals

weak_ptr.hpp:
  - Added get_pointer function template for weak_ptr


[SVN r15099]
2002-08-26 15:27:23 +00:00
John Maddock
e84eb3f1ba Added #pragma's to fix codeguard errors.
[SVN r14984]
2002-08-20 11:08:11 +00:00
Peter Dimov
92999be436 Corrected the shared_ptr(auto_ptr<Y> &) postcondition (reported by Maciej Sobczak)
[SVN r14953]
2002-08-19 16:23:07 +00:00
Peter Dimov
bd4f575567 HPUX 10.20 patch (problem reported by Tom Matelich)
[SVN r14943]
2002-08-17 13:33:41 +00:00
Peter Dimov
09016db3c3 Note added to shared_ptr(Y*, D).
[SVN r14942]
2002-08-17 13:05:25 +00:00
Peter Dimov
c2ee5172b0 Switched to <boost/detail/lightweight_test.hpp> for testing.
[SVN r14932]
2002-08-16 16:41:16 +00:00
Peter Dimov
8436c4d271 #pragma option -pc around use_count_is_zero added for Borland 5.5.1, to enable compilation with -ps set.
[SVN r14927]
2002-08-16 15:55:19 +00:00
Peter Dimov
a09c2e556f BOOST_NO_EXCEPTIONS support added.
[SVN r14835]
2002-08-14 12:27:22 +00:00
Peter Dimov
e650c7ff16 Changed BOOST_TEST(p) to BOOST_TEST(p? true: false) to make sure the right thing is being tested.
[SVN r14834]
2002-08-14 11:59:13 +00:00
Peter Dimov
c06b4206f2 #include <iostream> added.
[SVN r14813]
2002-08-13 15:58:12 +00:00
Peter Dimov
89435a6287 get_pointer added.
[SVN r14628]
2002-07-27 16:02:26 +00:00
Peter Dimov
5328674c2d Minor scoped_* fix (px -> ptr) (Thanks to Bertolt Mildner)
[SVN r14619]
2002-07-26 14:18:21 +00:00
Peter Dimov
927fe73093 Changed #ifdefs so that member templates aren't disabled by an empty config.hpp.
[SVN r14589]
2002-07-24 15:36:25 +00:00
Peter Dimov
053aa108e3 Tabs. Grrr.
[SVN r14588]
2002-07-24 14:14:17 +00:00
Peter Dimov
b5e5c35696 Minor updates.
[SVN r14580]
2002-07-24 10:20:30 +00:00
Peter Dimov
77ad156c52 Design notes updated.
[SVN r14575]
2002-07-23 19:12:40 +00:00
Peter Dimov
018c401e47 Best practices section, thread safety section, design notes added.
[SVN r14572]
2002-07-23 15:19:22 +00:00
Peter Dimov
f586d3f83e shared_ptr<void const> support added.
[SVN r14570]
2002-07-23 12:33:11 +00:00
Peter Dimov
3f0ebd4c71 'shared_from_this' added.
[SVN r14561]
2002-07-22 16:36:52 +00:00
Peter Dimov
33077bda71 Win64 patch (Tim Fenders)
[SVN r14537]
2002-07-19 20:06:35 +00:00
Peter Dimov
547888d507 Consistent 'bool' conversions; scoped_ptr(auto_ptr); get_pointer(scoped_ptr) added.
[SVN r14496]
2002-07-17 15:15:39 +00:00
Peter Dimov
af6fe18c9d Minor fixes.
[SVN r14464]
2002-07-15 12:52:29 +00:00
Peter Dimov
dca9628be3 Disabled some Borland warnings (David B. Held)
[SVN r14368]
2002-07-09 12:06:46 +00:00
Peter Dimov
d84fa738ef Sleep(0) changed to Sleep(1) to (hopefully) avoid livelocks.
[SVN r14226]
2002-06-22 15:55:01 +00:00
Peter Dimov
a322dc54dc Platform-specific spinlocks disabled by default unless BOOST_LWM_USE_SPINLOCK is defined.
[SVN r14213]
2002-06-20 15:16:03 +00:00
Peter Dimov
951c2b7e83 counted_base is now smaller
[SVN r14212]
2002-06-20 14:56:10 +00:00
Peter Dimov
23f68a5657 Added libstdc++ v3 specific lightweight_mutex and atomic_count (contributed by Lars Gullik Bjønnes)
[SVN r13999]
2002-05-21 16:48:20 +00:00
Peter Dimov
ecb0b4478b Typo fixed.
[SVN r13770]
2002-05-09 11:16:29 +00:00
Peter Dimov
70255d46bb Documented templated pointer constructors, revised the intro a bit.
[SVN r13665]
2002-05-04 14:27:21 +00:00
Peter Dimov
4653c3673b shared_ptr now autodetects counted_bases; minor test updates; intrusive_ptr no longer calls addref/release for NULL pointers.
[SVN r13602]
2002-05-01 11:22:22 +00:00
Peter Dimov
11eacab70e Made shared_ptr::share_ptr(Y * p) a member template.
[SVN r13551]
2002-04-23 14:56:42 +00:00
Peter Dimov
110c0021e2 counted_base default constructor added
[SVN r13542]
2002-04-22 18:01:19 +00:00
Peter Dimov
4c5e355a0b Bugfixes.
[SVN r13541]
2002-04-22 09:37:08 +00:00
Peter Dimov
fbc9028313 intrusive_ptr.hpp added (still experimental)
[SVN r13526]
2002-04-19 19:34:16 +00:00
Peter Dimov
9b800d4f84 Added more mem_fn, shared_ptr tests.
[SVN r13432]
2002-04-10 16:04:53 +00:00
Peter Dimov
513752eee5 Worked around an MSVC 6 bug (Markus Schoepflin)
[SVN r13430]
2002-04-10 14:12:12 +00:00
Beman Dawes
9eb1ba7e9f test_main args must be *[] not ** for new rev of test tools
[SVN r13381]
2002-04-06 21:44:37 +00:00
Peter Dimov
fb5b1a20d2 Small modifications.
[SVN r13212]
2002-03-15 22:03:56 +00:00
Peter Dimov
b89945d36a Added winapi.hpp and a CRITICAL_SECTION lightweight_mutex variant.
[SVN r13211]
2002-03-15 22:00:10 +00:00
Peter Dimov
220f35a0f1 Casts removed as unsafe, added intro paragraph about make_shared.
[SVN r13180]
2002-03-12 14:39:22 +00:00
Peter Dimov
72f83165e0 Removed casts as unsafe.
[SVN r13179]
2002-03-12 14:02:38 +00:00
Peter Dimov
c17f8c36c1 weak_ptr::expired() added; weak_ptr documentation updated.
[SVN r13141]
2002-03-08 16:56:16 +00:00
Peter Dimov
8e604a9da9 Disabled the linux-specific versions since using kernel headers is problematic. #define BOOST_USE_ASM_ATOMIC_H to get them back.
[SVN r12995]
2002-03-01 16:17:08 +00:00
Darin Adler
3e0233a26c Minor text updates in history section.
[SVN r12956]
2002-02-27 17:03:30 +00:00
Peter Dimov
aa98e2b37e Added lwm_irix.hpp (contributed by Dan Gohman)
[SVN r12955]
2002-02-27 16:35:15 +00:00
Peter Dimov
7b53c0040c More output.
[SVN r12852]
2002-02-18 12:39:32 +00:00
Peter Dimov
e6605637f8 BOOST_LWM_WIN32_USE_CRITICAL_SECTION option.
[SVN r12842]
2002-02-16 18:45:20 +00:00
Peter Dimov
6dfe0896e3 Untabified.
[SVN r12838]
2002-02-16 16:14:16 +00:00
Peter Dimov
9f295cbb48 Threaded test added.
[SVN r12837]
2002-02-16 16:09:08 +00:00
Peter Dimov
76c19e6111 Enabled lwm_linux.hpp in lightweight_mutex.hpp.
[SVN r12834]
2002-02-16 15:00:55 +00:00
Peter Dimov
6e6a2a013a Added lwm_linux.hpp
[SVN r12833]
2002-02-16 14:34:34 +00:00
Peter Dimov
2482e00224 Modified scoped_* to use checked_delete; HP aCC doesn't like the inline assertions.
[SVN r12832]
2002-02-16 13:23:01 +00:00
Peter Dimov
7981b647c3 lwm_nop fixed to not emit warnings on g++; locking code #ifdef'ed since compilers sometimes have trouble removing it.
[SVN r12822]
2002-02-15 18:07:42 +00:00
Peter Dimov
875bab352c Added a timing test for the single/multi threaded perf ratio (~2:1)
[SVN r12821]
2002-02-15 18:06:17 +00:00
Peter Dimov
862dc0001f Documented the bool conversion.
[SVN r12817]
2002-02-15 14:46:53 +00:00
Peter Dimov
adc3ec3851 Fixes.
[SVN r12816]
2002-02-15 14:19:30 +00:00
Peter Dimov
5a6cd1cf3e Added a default constructor to shared_count and shared_ptr for incomplete types (void).
[SVN r12815]
2002-02-15 13:31:58 +00:00
Douglas Gregor
5e2f514140 Added forward declaration of 'weak_count' class, which is referenced in
shared_count; the friend declaration does not suffice to forward-declare the
name.


[SVN r12813]
2002-02-14 23:08:30 +00:00
Peter Dimov
309e6dd82e Revised to match the style of the C++ standard.
[SVN r12806]
2002-02-14 17:12:07 +00:00
Peter Dimov
6c5d296722 Modified weak_ptr to reflect list comments.
[SVN r12793]
2002-02-13 13:16:15 +00:00
Peter Dimov
b1a1ab99aa Bug fixes.
[SVN r12787]
2002-02-12 20:38:31 +00:00
Peter Dimov
1b69c14f45 weak_ptr made thread safe, shared->weak conversions, lightweight_mutex added.
[SVN r12786]
2002-02-12 16:55:25 +00:00
Darin Adler
cd8dea78e6 Don't reinclude, since everything we need to include is already taken
care of by <boost/shared_ptr.hpp>.


[SVN r12776]
2002-02-09 17:18:38 +00:00
Peter Dimov
d77b35f333 Fix the g++ 2.9x operator!= ambiguity.
[SVN r12772]
2002-02-09 15:45:29 +00:00
Peter Dimov
6f7b927641 weak_ptr::operator< is now stable, shared_ptr_test has much better coverage.
[SVN r12769]
2002-02-09 12:34:05 +00:00
Darin Adler
d2e20cf56c Remove obsolete paragraph
[SVN r12767]
2002-02-09 02:54:00 +00:00
Darin Adler
a6126b1370 Fixed some broken internal links.
[SVN r12766]
2002-02-09 01:18:00 +00:00
Peter Dimov
87f0accb23 Minor fixes.
[SVN r12763]
2002-02-08 20:45:04 +00:00
Darin Adler
7add76dae8 Always say "private noncopyable" to avoid warnings.
[SVN r12762]
2002-02-08 20:08:15 +00:00
Peter Dimov
2a2f10fddd Borland 5.5.1 fix
[SVN r12761]
2002-02-08 18:40:49 +00:00
Darin Adler
0dd3285d56 New casts for smart pointers.
[SVN r12743]
2002-02-06 19:42:04 +00:00
Darin Adler
f9782387d9 Tweaks.
[SVN r12715]
2002-02-04 22:52:48 +00:00
Peter Dimov
e1567707b1 Tab removed :-)
[SVN r12701]
2002-02-04 19:45:11 +00:00
Beman Dawes
08df55159b Fix broken links
[SVN r12697]
2002-02-04 18:51:16 +00:00
Peter Dimov
c29cc62d66 Minor tweaks.
[SVN r12684]
2002-02-04 11:15:40 +00:00
Darin Adler
6ed07733cb Fix atomic_count.hpp includes, convert Macintosh newlines to Unix ones,
since Metrowerks supports either and the rest of Boost uses Unix ones.


[SVN r12683]
2002-02-04 08:00:20 +00:00
Darin Adler
ee3d3bd1e1 Mention thread safety feature.
[SVN r12676]
2002-02-03 17:50:11 +00:00
Darin Adler
758954a93f Documentation updates.
[SVN r12675]
2002-02-03 17:46:08 +00:00
Douglas Gregor
590757e2b2 Don't give default arguments to function parameters what subsequent parameters do not have default arguments
[SVN r12670]
2002-02-03 15:21:41 +00:00
Douglas Gregor
ddd6d54426 Need to include utility.hpp to get noncopyable
[SVN r12669]
2002-02-03 15:19:04 +00:00
Darin Adler
1a7cd887e4 New smart pointer documentation. Related clean-up of the smart pointer
library. Changing includes to include the new individual smart pointer
headers. Replacing old smart pointer library with an include of the new
smart pointer headers. Simplify ifdefs that involve the member templates
macros now that BOOST_MSVC6_MEMBER_TEMPLATES is also guaranteed to bet
set for platforms that have full member templates.


[SVN r12647]
2002-02-02 18:36:12 +00:00
Peter Dimov
d3c76575f9 templated copy constructor added.
[SVN r12644]
2002-02-02 16:19:45 +00:00
Peter Dimov
b224270cc0 auto_ptr& constructor now has no effects when exception is thrown
[SVN r12643]
2002-02-02 16:18:04 +00:00
Peter Dimov
8b5b780c2c better weak_ptr coverage
[SVN r12624]
2002-02-01 19:34:31 +00:00
Peter Dimov
39c10f739d added an auto_ptr & constructor to shared_count
[SVN r12623]
2002-02-01 18:40:35 +00:00
Darin Adler
4fdc84f29e Make the non-threads version work.
[SVN r12597]
2002-01-31 06:52:58 +00:00
Peter Dimov
a8efe20862 Comments added.
[SVN r12510]
2002-01-25 16:10:26 +00:00
Peter Dimov
58c5711b47 Added tests for the new smart pointers.
[SVN r12500]
2002-01-25 13:54:30 +00:00
Darin Adler
5d564a2f01 Add a self-assignment assert to reset(). Also add an overload of reset to
allow resetting to a new pointer with a new deletion function.


[SVN r12491]
2002-01-24 19:16:12 +00:00
Peter Dimov
09c1476063 Smart pointer enhancements, initial commit
[SVN r12439]
2002-01-22 13:38:52 +00:00
Beman Dawes
f255439ece add eof newline
[SVN r12358]
2002-01-19 15:54:28 +00:00
Peter Dimov
b104e9ae78 smart_ptr.hpp less<> fixed, partial specialization enabled on Sun 5.3
[SVN r12334]
2002-01-17 12:46:45 +00:00
Beman Dawes
4f964ce6ad Add FAQ: why no release()
[SVN r12286]
2002-01-11 20:20:07 +00:00
Beman Dawes
11ec515378 Fix broken link
[SVN r12285]
2002-01-11 16:15:09 +00:00
Beman Dawes
1a9b1dd123 1.25.0 Final runup
[SVN r11315]
2001-10-01 15:54:23 +00:00
Beman Dawes
a93dfc1837 Fix broken hyperlink
[SVN r10896]
2001-08-19 15:08:33 +00:00
Beman Dawes
c5846378ab More FAQ entries added.
[SVN r10605]
2001-07-13 16:32:34 +00:00
Beman Dawes
aea7d0c9c8 Add FAQ why use_count()?
[SVN r10604]
2001-07-13 14:07:08 +00:00
Beman Dawes
65c3f2dc85 Add table of contents, improve the FAQ
[SVN r10599]
2001-07-12 19:51:53 +00:00
Beman Dawes
5fbc553611 Reorder shared_ptr code so VC++ 6 member templates work, allowing polymorphic pointers to now work with that compiler (Gary Powell)
[SVN r10548]
2001-07-06 13:23:07 +00:00
Beman Dawes
c41b060618 Initial checkin
[SVN r10221]
2001-05-24 18:43:24 +00:00
Beman Dawes
c17921c417 Documentation and example program improvements
[SVN r10220]
2001-05-24 18:42:25 +00:00
Beman Dawes
94287044ba Oops! Fix boo boo from prior fix
[SVN r10206]
2001-05-24 01:32:07 +00:00
Beman Dawes
7c09884eac Move MS VC++ pragmas to workaround compiler crash reported by several people with SP4 and SP5.
[SVN r10204]
2001-05-23 20:14:15 +00:00
Beman Dawes
a90a157ea6 Smart pointer and utility changes related to adding checked_delere and checked_array_delete
[SVN r10189]
2001-05-22 18:58:21 +00:00
Beman Dawes
ac8d0f5505 Fix doc errors, add shared_ptr_example program
[SVN r10165]
2001-05-21 14:58:07 +00:00
Beman Dawes
8f23f07740 Fix transitive dependency bug
[SVN r10164]
2001-05-21 14:56:51 +00:00
Beman Dawes
3b183163c9 Clarify rationale for noncopyability
[SVN r10085]
2001-05-10 16:00:49 +00:00
Beman Dawes
55a377b446 Change all eGroups references to YahooGroups
[SVN r9979]
2001-04-25 00:24:50 +00:00
Beman Dawes
2d342f0ddf Comment corrected (thanks to Joe Gottman)
[SVN r9582]
2001-03-19 12:34:12 +00:00
Beman Dawes
060ea4a573 Add a couple of comments to cut down on FAQ's
[SVN r9581]
2001-03-18 22:25:51 +00:00
Beman Dawes
6a12efb77b 1.21.1 run up, including new download instructions and fix broken hyperlinks
[SVN r9557]
2001-03-14 15:11:55 +00:00
Beman Dawes
e57d3f4bc1 Fix revision date
[SVN r9069]
2001-02-10 12:47:02 +00:00
Beman Dawes
16902b1f4f Add example
[SVN r9054]
2001-02-09 14:39:43 +00:00
Dave Abrahams
cb1b1b7cc0 Suppress some useless warnings with MSVC
[SVN r8704]
2001-01-22 04:53:38 +00:00
Beman Dawes
26fe4c4078 Fix typo shared_array should have read shared_ptr in one place (Ed Brey)
[SVN r8392]
2000-12-06 14:46:44 +00:00
John Maddock
4e832788bf Fix for egcs 1.1.1 problems with std::auto_ptr
[SVN r8225]
2000-11-16 11:17:22 +00:00
Beman Dawes
db43d160b4 libraries.htm and people.htm moved to sub-directories to make root directory cleaner.
[SVN r8166]
2000-11-10 15:39:05 +00:00
Beman Dawes
1412e40490 Make shared_ptr ctor from auto_ptr explicit. (Robert Vugts)
[SVN r8012]
2000-10-19 21:16:46 +00:00
Beman Dawes
00c5642eb4 1.17.0 release candidate runup
[SVN r7683]
2000-08-03 15:26:16 +00:00
Beman Dawes
d3347b6d08 Initial HTML commit
[SVN r7640]
2000-07-27 14:27:00 +00:00
Beman Dawes
ed7e13da9f Initial commit
[SVN r7638]
2000-07-27 14:18:23 +00:00
Beman Dawes
90b7ec19d1 Changed throw() to // never throws.
[SVN r7628]
2000-07-24 16:21:10 +00:00
Beman Dawes
468c41041b This commit was generated by cvs2svn to compensate for changes in r4,
which included commits to RCS files with non-trunk default branches.


[SVN r7621]
2000-07-07 16:04:40 +00:00
153 changed files with 23921 additions and 0 deletions

88
compatibility.htm Normal file
View File

@@ -0,0 +1,88 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Smart Pointer Changes</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff" text="#000000">
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
border="0"></A>Smart Pointer Changes</h1>
<p>The February 2002 change to the Boost smart pointers introduced a number of
changes. Since the previous version of the smart pointers was in use for a long
time, it's useful to have a detailed list of what changed from a library user's
point of view.</p>
<p>Note that for compilers that don't support member templates well enough, a
separate implementation is used that lacks many of the new features and is more
like the old version.</p>
<h2>Features Requiring Code Changes to Take Advantage</h2>
<ul>
<li>
The smart pointer class templates now each have their own header file. For
compatibility, the <a href="../../boost/smart_ptr.hpp">&lt;boost/smart_ptr.hpp&gt;</a>
header now includes the headers for the four classic smart pointer class
templates.
<li>
The <b>weak_ptr</b>
template was added.
<li>
The new <b>shared_ptr</b> and <b>shared_array</b> relax the requirement that
the pointed-to object's destructor must be visible when instantiating the <b>shared_ptr</b>
destructor. This makes it easier to have shared_ptr members in classes without
explicit destructors.
<li>
A custom deallocator can be passed in when creating a <b>shared_ptr</b> or <b>shared_array</b>.
<li>
<b>shared_static_cast</b> and <b>shared_dynamic_cast</b> function templates are
provided which work for <b>shared_ptr</b> and <b>weak_ptr</b> as <b>static_cast</b>
and <b>dynamic_cast</b>
do for pointers.
<li>
The self-assignment misfeature has been removed from <b>shared_ptr::reset</b>,
although it is still present in <b>scoped_ptr</b>, and in <b>std::auto_ptr</b>.
Calling <b>reset</b> with a pointer to the object that's already owned by the <b>shared_ptr</b>
results in undefined behavior (an assertion, or eventually a double-delete if
assertions are off).
<li>
The <b>BOOST_SMART_PTR_CONVERSION</b>
feature has been removed.
<li>
<b>shared_ptr&lt;void&gt;</b> is now allowed.</li>
</ul>
<h2>Features That Improve Robustness</h2>
<ul>
<li>
The manipulation of use counts is now <a name="threadsafe">thread safe</a> on
Windows, Linux, and platforms that support pthreads. See the <a href="../../boost/detail/atomic_count.hpp">
&lt;boost/detail/atomic_count.hpp&gt;</a>
file for details
<li>
The new shared_ptr will always delete the object using the pointer it was
originally constructed with. This prevents subtle problems that could happen if
the last <b>shared_ptr</b> was a pointer to a sub-object of a class that did
not have a virtual destructor.</li>
</ul>
<h2>Implementation Details</h2>
<ul>
<li>
Some bugs in the assignment operator implementations and in <b>reset</b>
have been fixed by using the "copy and swap" idiom.
<li>
Assertions have been added to check preconditions of various functions;
however, since these use the new <a href="../../boost/assert.hpp">&lt;boost/assert.hpp&gt;</a>
header, the assertions are disabled by default.
<li>
The partial specialization of <b>std::less</b> has been replaced by <b>operator&lt;</b>
overloads which accomplish the same thing without relying on undefined
behavior.
<li>
The incorrect overload of <b>std::swap</b> has been replaced by <b>boost::swap</b>,
which has many of the same advantages for generic programming but does not
violate the C++ standard.</li>
</ul>
<hr>
<p>Revised 1 February 2002</p>
<p><small>Copyright 2002 Darin Adler. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

View File

@@ -0,0 +1,95 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Boost: enable_shared_from_this.hpp documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
<table border="0" width="100%">
<tr>
<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A>
</td>
<td align="center">
<h1>enable_shared_from_this.hpp</h1>
</td>
</tr>
<tr>
<td colspan="2" height="64">&nbsp;</td>
</tr>
</table>
<h3><a name="Purpose">Purpose</a></h3>
<p>
The header <STRONG>&lt;boost/enable_shared_from_this.hpp&gt;</STRONG> defines
the class template <STRONG>enable_shared_from_this</STRONG>. It is used as a
base class that allows a <A href="shared_ptr.htm">shared_ptr</A> to the current
object to be obtained from within a member function.
</p>
<P><STRONG>enable_shared_from_this&lt;T&gt;</STRONG> defines two member functions
called <STRONG>shared_from_this</STRONG> that return a <STRONG>shared_ptr&lt;T&gt;</STRONG>
and <STRONG>shared_ptr&lt;T const&gt;</STRONG>, depending on constness, to <STRONG>this</STRONG>.</P>
<h3><a name="Example">Example</a></h3>
<pre>
#include &lt;boost/enable_shared_from_this.hpp&gt;
#include &lt;boost/shared_ptr.hpp&gt;
#include &lt;cassert&gt;
class Y: public boost::enable_shared_from_this&lt;Y&gt;
{
public:
boost::shared_ptr&lt;Y&gt; f()
{
return shared_from_this();
}
};
int main()
{
boost::shared_ptr&lt;Y&gt; p(new Y);
boost::shared_ptr&lt;Y&gt; q = p-&gt;f();
assert(p == q);
assert(!(p &lt; q || q &lt; p)); // p and q must share ownership
}
</pre>
<h3><a name="Synopsis">Synopsis</a></h3>
<pre>
namespace boost
{
template&lt;class T&gt; class enable_shared_from_this
{
public:
shared_ptr&lt;T&gt; shared_from_this();
shared_ptr&lt;T const&gt; shared_from_this() const;
}
}
</pre>
<h4>template&lt;class T&gt; shared_ptr&lt;T&gt;
enable_shared_from_this&lt;T&gt;::shared_from_this();</h4>
<h4>template&lt;class T&gt; shared_ptr&lt;T const&gt;
enable_shared_from_this&lt;T&gt;::shared_from_this() const;</h4>
<blockquote>
<p>
<b>Requires:</b> <STRONG>enable_shared_from_this&lt;T&gt;</STRONG> must be an
accessible base class of <b>T</b>. <STRONG>*this</STRONG> must be a subobject
of an instance <STRONG>t</STRONG> of type <STRONG>T</STRONG> . There must exist
at least one <STRONG>shared_ptr</STRONG> instance <STRONG>p</STRONG> that <EM>owns</EM>
<STRONG>t</STRONG>.
</p>
<p>
<b>Returns:</b> A <b>shared_ptr&lt;T&gt;</b> instance <b>r</b> that shares
ownership with <b>p</b>.
</p>
<p>
<b>Postconditions:</b> <tt>r.get() == this</tt>.
</p>
</blockquote>
<p>
<br>
<small>Copyright <20> 2002, 2003 by Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

View File

@@ -0,0 +1,23 @@
// Boost scoped_ptr_example implementation file -----------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "scoped_ptr_example.hpp"
#include <iostream>
class example::implementation
{
public:
~implementation() { std::cout << "destroying implementation\n"; }
};
example::example() : _imp( new implementation ) {}
void example::do_something() { std::cout << "did something\n"; }
example::~example() {}

View File

@@ -0,0 +1,29 @@
// Boost scoped_ptr_example header file ------------------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp>
// The point of this example is to prove that even though
// example::implementation is an incomplete type in translation units using
// this header, scoped_ptr< implementation > is still valid because the type
// is complete where it counts - in the inplementation translation unit where
// destruction is actually instantiated.
class example : private boost::noncopyable
{
public:
example();
~example();
void do_something();
private:
class implementation;
boost::scoped_ptr< implementation > _imp; // hide implementation details
};

View File

@@ -0,0 +1,17 @@
// Boost scoped_ptr_example_test main program -------------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "scoped_ptr_example.hpp"
int main()
{
example my_example;
my_example.do_something();
return 0;
}

View File

@@ -0,0 +1,95 @@
// Boost shared_ptr_example.cpp --------------------------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
// Revision History
// 21 May 01 Initial complete version (Beman Dawes)
// The original code for this example appeared in the shared_ptr documentation.
// Ray Gallimore pointed out that foo_set was missing a Compare template
// argument, so would not work as intended. At that point the code was
// turned into an actual .cpp file so it could be compiled and tested.
#include <vector>
#include <set>
#include <iostream>
#include <algorithm>
#include <boost/shared_ptr.hpp>
// The application will produce a series of
// objects of type Foo which later must be
// accessed both by occurrence (std::vector)
// and by ordering relationship (std::set).
struct Foo
{
Foo( int _x ) : x(_x) {}
~Foo() { std::cout << "Destructing a Foo with x=" << x << "\n"; }
int x;
/* ... */
};
typedef boost::shared_ptr<Foo> FooPtr;
struct FooPtrOps
{
bool operator()( const FooPtr & a, const FooPtr & b )
{ return a->x > b->x; }
void operator()( const FooPtr & a )
{ std::cout << a->x << "\n"; }
};
int main()
{
std::vector<FooPtr> foo_vector;
std::set<FooPtr,FooPtrOps> foo_set; // NOT multiset!
FooPtr foo_ptr( new Foo( 2 ) );
foo_vector.push_back( foo_ptr );
foo_set.insert( foo_ptr );
foo_ptr.reset( new Foo( 1 ) );
foo_vector.push_back( foo_ptr );
foo_set.insert( foo_ptr );
foo_ptr.reset( new Foo( 3 ) );
foo_vector.push_back( foo_ptr );
foo_set.insert( foo_ptr );
foo_ptr.reset ( new Foo( 2 ) );
foo_vector.push_back( foo_ptr );
foo_set.insert( foo_ptr );
std::cout << "foo_vector:\n";
std::for_each( foo_vector.begin(), foo_vector.end(), FooPtrOps() );
std::cout << "\nfoo_set:\n";
std::for_each( foo_set.begin(), foo_set.end(), FooPtrOps() );
std::cout << "\n";
// Expected output:
//
// foo_vector:
// 2
// 1
// 3
// 2
//
// foo_set:
// 3
// 2
// 1
//
// Destructing a Foo with x=2
// Destructing a Foo with x=1
// Destructing a Foo with x=3
// Destructing a Foo with x=2
return 0;
}

View File

@@ -0,0 +1,22 @@
// Boost shared_ptr_example2 implementation file -----------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "shared_ptr_example2.hpp"
#include <iostream>
class example::implementation
{
public:
~implementation() { std::cout << "destroying implementation\n"; }
};
example::example() : _imp( new implementation ) {}
void example::do_something()
{ std::cout << "use_count() is " << _imp.use_count() << "\n"; }

View File

@@ -0,0 +1,31 @@
// Boost shared_ptr_example2 header file -----------------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include <boost/shared_ptr.hpp>
// This example demonstrates the handle/body idiom (also called pimpl and
// several other names). It separates the interface (in this header file)
// from the implementation (in shared_ptr_example2.cpp).
// Note that even though example::implementation is an incomplete type in
// some translation units using this header, shared_ptr< implementation >
// is still valid because the type is complete where it counts - in the
// shared_ptr_example2.cpp translation unit where functions requiring a
// complete type are actually instantiated.
class example
{
public:
example();
void do_something();
private:
class implementation;
boost::shared_ptr< implementation > _imp; // hide implementation details
};

View File

@@ -0,0 +1,22 @@
// Boost shared_ptr_example2_test main program ------------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/smart_ptr for documentation.
#include "shared_ptr_example2.hpp"
int main()
{
example a;
a.do_something();
example b(a);
b.do_something();
example c;
c = a;
c.do_something();
return 0;
}

BIN
gccspeed.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@@ -0,0 +1,21 @@
#ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
#define BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/detail/atomic_count.hpp - thread/SMP safe reference counter
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/smart_ptr/detail/atomic_count.hpp>
#endif // #ifndef BOOST_DETAIL_ATOMIC_COUNT_HPP_INCLUDED

View File

@@ -0,0 +1,22 @@
#ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
#define BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/detail/lightweight_mutex.hpp - lightweight mutex
//
// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/smart_ptr/detail/lightweight_mutex.hpp>
#endif // #ifndef BOOST_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED

View File

@@ -0,0 +1,129 @@
#ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
#define BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// detail/sp_typeinfo.hpp
//
// Copyright 2007 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#if defined( BOOST_NO_TYPEID )
#include <boost/current_function.hpp>
#include <functional>
namespace boost
{
namespace detail
{
class sp_typeinfo
{
private:
sp_typeinfo( sp_typeinfo const& );
sp_typeinfo& operator=( sp_typeinfo const& );
char const * name_;
public:
explicit sp_typeinfo( char const * name ): name_( name )
{
}
bool operator==( sp_typeinfo const& rhs ) const
{
return this == &rhs;
}
bool operator!=( sp_typeinfo const& rhs ) const
{
return this != &rhs;
}
bool before( sp_typeinfo const& rhs ) const
{
return std::less< sp_typeinfo const* >()( this, &rhs );
}
char const* name() const
{
return name_;
}
};
template<class T> struct sp_typeid_
{
static sp_typeinfo ti_;
static char const * name()
{
return BOOST_CURRENT_FUNCTION;
}
};
template<class T> sp_typeinfo sp_typeid_< T >::ti_( sp_typeid_< T >::name() );
template<class T> struct sp_typeid_< T & >: sp_typeid_< T >
{
};
template<class T> struct sp_typeid_< T const >: sp_typeid_< T >
{
};
template<class T> struct sp_typeid_< T volatile >: sp_typeid_< T >
{
};
template<class T> struct sp_typeid_< T const volatile >: sp_typeid_< T >
{
};
} // namespace detail
} // namespace boost
#define BOOST_SP_TYPEID(T) (boost::detail::sp_typeid_<T>::ti_)
#else
#include <typeinfo>
namespace boost
{
namespace detail
{
#if defined( BOOST_NO_STD_TYPEINFO )
typedef ::type_info sp_typeinfo;
#else
typedef std::type_info sp_typeinfo;
#endif
} // namespace detail
} // namespace boost
#define BOOST_SP_TYPEID(T) typeid(T)
#endif
#endif // #ifndef BOOST_DETAIL_SP_TYPEINFO_HPP_INCLUDED

View File

@@ -0,0 +1,18 @@
#ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
#define BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
//
// enable_shared_from_this.hpp
//
// Copyright (c) 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
//
#include <boost/smart_ptr/enable_shared_from_this.hpp>
#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED

View File

@@ -0,0 +1,33 @@
// Copyright Peter Dimov and David Abrahams 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef GET_POINTER_DWA20021219_HPP
# define GET_POINTER_DWA20021219_HPP
// In order to avoid circular dependencies with Boost.TR1
// we make sure that our include of <memory> doesn't try to
// pull in the TR1 headers: that's why we use this header
// rather than including <memory> directly:
# include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
namespace boost {
// get_pointer(p) extracts a ->* capable pointer from p
template<class T> T * get_pointer(T * p)
{
return p;
}
// get_pointer(shared_ptr<T> const & p) has been moved to shared_ptr.hpp
template<class T> T * get_pointer(std::auto_ptr<T> const& p)
{
return p.get();
}
} // namespace boost
#endif // GET_POINTER_DWA20021219_HPP

View File

@@ -0,0 +1,18 @@
#ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED
#define BOOST_INTRUSIVE_PTR_HPP_INCLUDED
//
// intrusive_ptr.hpp
//
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation.
//
#include <boost/smart_ptr/intrusive_ptr.hpp>
#endif // #ifndef BOOST_INTRUSIVE_PTR_HPP_INCLUDED

View File

@@ -0,0 +1,17 @@
#ifndef BOOST_MAKE_SHARED_HPP_INCLUDED
#define BOOST_MAKE_SHARED_HPP_INCLUDED
// make_shared.hpp
//
// Copyright (c) 2007, 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://www.boost.org/libs/smart_ptr/make_shared.html
// for documentation.
#include <boost/smart_ptr/make_shared.hpp>
#endif // #ifndef BOOST_MAKE_SHARED_HPP_INCLUDED

View File

@@ -0,0 +1,53 @@
#ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED
#define BOOST_MEMORY_ORDER_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// boost/memory_order.hpp
//
// Defines enum boost::memory_order per the C++0x working draft
//
// Copyright (c) 2008, 2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
namespace boost
{
//
// Enum values are chosen so that code that needs to insert
// a trailing fence for acquire semantics can use a single
// test such as:
//
// if( mo & memory_order_acquire ) { ...fence... }
//
// For leading fences one can use:
//
// if( mo & memory_order_release ) { ...fence... }
//
// Architectures such as Alpha that need a fence on consume
// can use:
//
// if( mo & ( memory_order_acquire | memory_order_consume ) ) { ...fence... }
//
enum memory_order
{
memory_order_relaxed = 0,
memory_order_acquire = 1,
memory_order_release = 2,
memory_order_acq_rel = 3, // acquire | release
memory_order_seq_cst = 7, // acq_rel | 4
memory_order_consume = 8
};
} // namespace boost
#endif // #ifndef BOOST_MEMORY_ORDER_HPP_INCLUDED

View File

@@ -0,0 +1,45 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_POINTER_CAST_HPP
#define BOOST_POINTER_CAST_HPP
namespace boost {
//static_pointer_cast overload for raw pointers
template<class T, class U>
inline T* static_pointer_cast(U *ptr)
{
return static_cast<T*>(ptr);
}
//dynamic_pointer_cast overload for raw pointers
template<class T, class U>
inline T* dynamic_pointer_cast(U *ptr)
{
return dynamic_cast<T*>(ptr);
}
//const_pointer_cast overload for raw pointers
template<class T, class U>
inline T* const_pointer_cast(U *ptr)
{
return const_cast<T*>(ptr);
}
//reinterpret_pointer_cast overload for raw pointers
template<class T, class U>
inline T* reinterpret_pointer_cast(U *ptr)
{
return reinterpret_cast<T*>(ptr);
}
} // namespace boost
#endif //BOOST_POINTER_CAST_HPP

View File

@@ -0,0 +1,55 @@
#ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED
#define BOOST_POINTER_TO_OTHER_HPP_INCLUDED
//
// pointer_to_other.hpp
//
// (C) Copyright Ion Gaztanaga 2005.
// Copyright (c) 2005 Peter Dimov.
//
// Distributed under the Boost Software License, Version 1.0.
//
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/pointer_to_other.html
//
namespace boost
{
// Defines the same pointer type (raw or smart) to another pointee type
template<class T, class U>
struct pointer_to_other;
template<class T, class U,
template<class> class Sp>
struct pointer_to_other< Sp<T>, U >
{
typedef Sp<U> type;
};
template<class T, class T2, class U,
template<class, class> class Sp>
struct pointer_to_other< Sp<T, T2>, U >
{
typedef Sp<U, T2> type;
};
template<class T, class T2, class T3, class U,
template<class, class, class> class Sp>
struct pointer_to_other< Sp<T, T2, T3>, U >
{
typedef Sp<U, T2, T3> type;
};
template<class T, class U>
struct pointer_to_other< T*, U >
{
typedef U* type;
};
} // namespace boost
#endif // #ifndef BOOST_POINTER_TO_OTHER_HPP_INCLUDED

View File

@@ -0,0 +1,16 @@
#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED
#define BOOST_SCOPED_ARRAY_HPP_INCLUDED
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// http://www.boost.org/libs/smart_ptr/scoped_array.htm
//
#include <boost/smart_ptr/scoped_array.hpp>
#endif // #ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED

View File

@@ -0,0 +1,16 @@
#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED
#define BOOST_SCOPED_PTR_HPP_INCLUDED
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
//
#include <boost/smart_ptr/scoped_ptr.hpp>
#endif // #ifndef BOOST_SCOPED_PTR_HPP_INCLUDED

View File

@@ -0,0 +1,19 @@
#ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED
#define BOOST_SHARED_ARRAY_HPP_INCLUDED
//
// shared_array.hpp
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation.
//
#include <boost/smart_ptr/shared_array.hpp>
#endif // #ifndef BOOST_SHARED_ARRAY_HPP_INCLUDED

View File

@@ -0,0 +1,19 @@
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
#define BOOST_SHARED_PTR_HPP_INCLUDED
//
// shared_ptr.hpp
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001-2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
//
#include <boost/smart_ptr/shared_ptr.hpp>
#endif // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED

View File

@@ -0,0 +1,25 @@
//
// smart_ptr.hpp
//
// For convenience, this header includes the rest of the smart
// pointer library headers.
//
// Copyright (c) 2003 Peter Dimov Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// http://www.boost.org/libs/smart_ptr/smart_ptr.htm
//
#include <boost/config.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/shared_array.hpp>
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
# include <boost/weak_ptr.hpp>
# include <boost/intrusive_ptr.hpp>
# include <boost/enable_shared_from_this.hpp>
#endif

View File

@@ -0,0 +1,59 @@
#ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED
#define BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/smart_ptr/bad_weak_ptr.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <exception>
#ifdef __BORLANDC__
# pragma warn -8026 // Functions with excep. spec. are not expanded inline
#endif
namespace boost
{
// The standard library that comes with Borland C++ 5.5.1, 5.6.4
// defines std::exception and its members as having C calling
// convention (-pc). When the definition of bad_weak_ptr
// is compiled with -ps, the compiler issues an error.
// Hence, the temporary #pragma option -pc below.
#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
# pragma option push -pc
#endif
class bad_weak_ptr: public std::exception
{
public:
virtual char const * what() const throw()
{
return "tr1::bad_weak_ptr";
}
};
#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
# pragma option pop
#endif
} // namespace boost
#ifdef __BORLANDC__
# pragma warn .8026 // Functions with excep. spec. are not expanded inline
#endif
#endif // #ifndef BOOST_SMART_PTR_BAD_WEAK_PTR_HPP_INCLUDED

View File

@@ -0,0 +1,119 @@
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/detail/atomic_count.hpp - thread/SMP safe reference counter
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// typedef <implementation-defined> boost::detail::atomic_count;
//
// atomic_count a(n);
//
// (n is convertible to long)
//
// Effects: Constructs an atomic_count with an initial value of n
//
// a;
//
// Returns: (long) the current value of a
//
// ++a;
//
// Effects: Atomically increments the value of a
// Returns: (long) the new value of a
//
// --a;
//
// Effects: Atomically decrements the value of a
// Returns: (long) the new value of a
//
// Important note: when --a returns zero, it must act as a
// read memory barrier (RMB); i.e. the calling thread must
// have a synchronized view of the memory
//
// On Intel IA-32 (x86) memory is always synchronized, so this
// is not a problem.
//
// On many architectures the atomic instructions already act as
// a memory barrier.
//
// This property is necessary for proper reference counting, since
// a thread can update the contents of a shared object, then
// release its reference, and another thread may immediately
// release the last reference causing object destruction.
//
// The destructor needs to have a synchronized view of the
// object to perform proper cleanup.
//
// Original example by Alexander Terekhov:
//
// Given:
//
// - a mutable shared object OBJ;
// - two threads THREAD1 and THREAD2 each holding
// a private smart_ptr object pointing to that OBJ.
//
// t1: THREAD1 updates OBJ (thread-safe via some synchronization)
// and a few cycles later (after "unlock") destroys smart_ptr;
//
// t2: THREAD2 destroys smart_ptr WITHOUT doing any synchronization
// with respect to shared mutable object OBJ; OBJ destructors
// are called driven by smart_ptr interface...
//
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
#ifndef BOOST_HAS_THREADS
namespace boost
{
namespace detail
{
typedef long atomic_count;
}
}
#elif defined(BOOST_AC_USE_PTHREADS)
# include <boost/smart_ptr/detail/atomic_count_pthreads.hpp>
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
# include <boost/smart_ptr/detail/atomic_count_gcc_x86.hpp>
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# include <boost/smart_ptr/detail/atomic_count_win32.hpp>
#elif defined( BOOST_SP_HAS_SYNC )
# include <boost/smart_ptr/detail/atomic_count_sync.hpp>
#elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
# include <boost/smart_ptr/detail/atomic_count_gcc.hpp>
#elif defined(BOOST_HAS_PTHREADS)
# define BOOST_AC_USE_PTHREADS
# include <boost/smart_ptr/detail/atomic_count_pthreads.hpp>
#else
// Use #define BOOST_DISABLE_THREADS to avoid the error
#error Unrecognized threading platform
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_HPP_INCLUDED

View File

@@ -0,0 +1,72 @@
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED
//
// boost/detail/atomic_count_gcc.hpp
//
// atomic_count for GNU libstdc++ v3
//
// http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2002 Lars Gullik Bj<42>nnes <larsbj@lyx.org>
// Copyright 2003-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#if __GNUC__ * 100 + __GNUC_MINOR__ >= 402
# include <ext/atomicity.h>
#else
# include <bits/atomicity.h>
#endif
namespace boost
{
namespace detail
{
#if defined(__GLIBCXX__) // g++ 3.4+
using __gnu_cxx::__atomic_add;
using __gnu_cxx::__exchange_and_add;
#endif
class atomic_count
{
public:
explicit atomic_count( long v ) : value_( v ) {}
long operator++()
{
return __exchange_and_add( &value_, +1 ) + 1;
}
long operator--()
{
return __exchange_and_add( &value_, -1 ) - 1;
}
operator long() const
{
return __exchange_and_add( &value_, 0 );
}
private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
mutable _Atomic_word value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_HPP_INCLUDED

View File

@@ -0,0 +1,77 @@
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED
//
// boost/detail/atomic_count_gcc_x86.hpp
//
// atomic_count for g++ on 486+/AMD64
//
// Copyright 2007 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
namespace boost
{
namespace detail
{
class atomic_count
{
public:
explicit atomic_count( long v ) : value_( static_cast< int >( v ) ) {}
long operator++()
{
return atomic_exchange_and_add( &value_, +1 ) + 1;
}
long operator--()
{
return atomic_exchange_and_add( &value_, -1 ) - 1;
}
operator long() const
{
return atomic_exchange_and_add( &value_, 0 );
}
private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
mutable int value_;
private:
static int atomic_exchange_and_add( int * pw, int dv )
{
// int r = *pw;
// *pw += dv;
// return r;
int r;
__asm__ __volatile__
(
"lock\n\t"
"xadd %1, %0":
"+m"( *pw ), "=r"( r ): // outputs (%0, %1)
"1"( dv ): // inputs (%2 == %1)
"memory", "cc" // clobbers
);
return r;
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_X86_HPP_INCLUDED

View File

@@ -0,0 +1,96 @@
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED
//
// boost/detail/atomic_count_pthreads.hpp
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <pthread.h>
//
// The generic pthread_mutex-based implementation sometimes leads to
// inefficiencies. Example: a class with two atomic_count members
// can get away with a single mutex.
//
// Users can detect this situation by checking BOOST_AC_USE_PTHREADS.
//
namespace boost
{
namespace detail
{
class atomic_count
{
private:
class scoped_lock
{
public:
scoped_lock(pthread_mutex_t & m): m_(m)
{
pthread_mutex_lock(&m_);
}
~scoped_lock()
{
pthread_mutex_unlock(&m_);
}
private:
pthread_mutex_t & m_;
};
public:
explicit atomic_count(long v): value_(v)
{
pthread_mutex_init(&mutex_, 0);
}
~atomic_count()
{
pthread_mutex_destroy(&mutex_);
}
long operator++()
{
scoped_lock lock(mutex_);
return ++value_;
}
long operator--()
{
scoped_lock lock(mutex_);
return --value_;
}
operator long() const
{
scoped_lock lock(mutex_);
return value_;
}
private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
mutable pthread_mutex_t mutex_;
long value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_PTHREADS_HPP_INCLUDED

View File

@@ -0,0 +1,59 @@
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED
//
// boost/detail/atomic_count_solaris.hpp
// based on: boost/detail/atomic_count_win32.hpp
//
// Copyright (c) 2001-2005 Peter Dimov
// Copyright (c) 2006 Michael van der Westhuizen
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <atomic.h>
namespace boost
{
namespace detail
{
class atomic_count
{
public:
explicit atomic_count( uint32_t v ): value_( v )
{
}
long operator++()
{
return atomic_inc_32_nv( &value_ );
}
long operator--()
{
return atomic_dec_32_nv( &value_ );
}
operator uint32_t() const
{
return static_cast<uint32_t const volatile &>( value_ );
}
private:
atomic_count( atomic_count const & );
atomic_count & operator=( atomic_count const & );
uint32_t value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SOLARIS_HPP_INCLUDED

View File

@@ -0,0 +1,61 @@
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED
//
// boost/detail/atomic_count_sync.hpp
//
// atomic_count for g++ 4.1+
//
// http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Atomic-Builtins.html
//
// Copyright 2007 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#if defined( __ia64__ ) && defined( __INTEL_COMPILER )
# include <ia64intrin.h>
#endif
namespace boost
{
namespace detail
{
class atomic_count
{
public:
explicit atomic_count( long v ) : value_( v ) {}
long operator++()
{
return __sync_add_and_fetch( &value_, 1 );
}
long operator--()
{
return __sync_add_and_fetch( &value_, -1 );
}
operator long() const
{
return __sync_fetch_and_add( &value_, 0 );
}
private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
mutable long value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_SYNC_HPP_INCLUDED

View File

@@ -0,0 +1,63 @@
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/detail/atomic_count_win32.hpp
//
// Copyright (c) 2001-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/interlocked.hpp>
namespace boost
{
namespace detail
{
class atomic_count
{
public:
explicit atomic_count( long v ): value_( v )
{
}
long operator++()
{
return BOOST_INTERLOCKED_INCREMENT( &value_ );
}
long operator--()
{
return BOOST_INTERLOCKED_DECREMENT( &value_ );
}
operator long() const
{
return static_cast<long const volatile &>( value_ );
}
private:
atomic_count( atomic_count const & );
atomic_count & operator=( atomic_count const & );
long value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_WIN32_HPP_INCLUDED

View File

@@ -0,0 +1,42 @@
#ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/detail/lightweight_mutex.hpp - lightweight mutex
//
// Copyright (c) 2002, 2003 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// typedef <unspecified> boost::detail::lightweight_mutex;
//
// boost::detail::lightweight_mutex is a header-only implementation of
// a subset of the Mutex concept requirements:
//
// http://www.boost.org/doc/html/threads/concepts.html#threads.concepts.Mutex
//
// It maps to a CRITICAL_SECTION on Windows or a pthread_mutex on POSIX.
//
#include <boost/config.hpp>
#if !defined(BOOST_HAS_THREADS)
# include <boost/smart_ptr/detail/lwm_nop.hpp>
#elif defined(BOOST_HAS_PTHREADS)
# include <boost/smart_ptr/detail/lwm_pthreads.hpp>
#elif defined(BOOST_HAS_WINTHREADS) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# include <boost/smart_ptr/detail/lwm_win32_cs.hpp>
#else
// Use #define BOOST_DISABLE_THREADS to avoid the error
# error Unrecognized threading platform
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED

View File

@@ -0,0 +1,37 @@
#ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/detail/lwm_nop.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
namespace boost
{
namespace detail
{
class lightweight_mutex
{
public:
typedef lightweight_mutex scoped_lock;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_NOP_HPP_INCLUDED

View File

@@ -0,0 +1,87 @@
#ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/detail/lwm_pthreads.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/assert.hpp>
#include <pthread.h>
namespace boost
{
namespace detail
{
class lightweight_mutex
{
private:
pthread_mutex_t m_;
lightweight_mutex(lightweight_mutex const &);
lightweight_mutex & operator=(lightweight_mutex const &);
public:
lightweight_mutex()
{
// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
#if defined(__hpux) && defined(_DECTHREADS_)
BOOST_VERIFY( pthread_mutex_init( &m_, pthread_mutexattr_default ) == 0 );
#else
BOOST_VERIFY( pthread_mutex_init( &m_, 0 ) == 0 );
#endif
}
~lightweight_mutex()
{
BOOST_VERIFY( pthread_mutex_destroy( &m_ ) == 0 );
}
class scoped_lock;
friend class scoped_lock;
class scoped_lock
{
private:
pthread_mutex_t & m_;
scoped_lock(scoped_lock const &);
scoped_lock & operator=(scoped_lock const &);
public:
scoped_lock(lightweight_mutex & m): m_(m.m_)
{
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
}
~scoped_lock()
{
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
}
};
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_PTHREADS_HPP_INCLUDED

View File

@@ -0,0 +1,108 @@
#ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/detail/lwm_win32_cs.hpp
//
// Copyright (c) 2002, 2003 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifdef BOOST_USE_WINDOWS_H
# include <windows.h>
#endif
namespace boost
{
namespace detail
{
#ifndef BOOST_USE_WINDOWS_H
struct critical_section
{
struct critical_section_debug * DebugInfo;
long LockCount;
long RecursionCount;
void * OwningThread;
void * LockSemaphore;
#if defined(_WIN64)
unsigned __int64 SpinCount;
#else
unsigned long SpinCount;
#endif
};
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *);
extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *);
extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *);
extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *);
#else
typedef ::CRITICAL_SECTION critical_section;
#endif // #ifndef BOOST_USE_WINDOWS_H
class lightweight_mutex
{
private:
critical_section cs_;
lightweight_mutex(lightweight_mutex const &);
lightweight_mutex & operator=(lightweight_mutex const &);
public:
lightweight_mutex()
{
InitializeCriticalSection(&cs_);
}
~lightweight_mutex()
{
DeleteCriticalSection(&cs_);
}
class scoped_lock;
friend class scoped_lock;
class scoped_lock
{
private:
lightweight_mutex & m_;
scoped_lock(scoped_lock const &);
scoped_lock & operator=(scoped_lock const &);
public:
explicit scoped_lock(lightweight_mutex & m): m_(m)
{
EnterCriticalSection(&m_.cs_);
}
~scoped_lock()
{
LeaveCriticalSection(&m_.cs_);
}
};
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_WIN32_CS_HPP_INCLUDED

View File

@@ -0,0 +1,56 @@
// This header intentionally has no include guards.
//
// Copyright (c) 2001-2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)
operator bool () const
{
return px != 0;
}
#elif defined( _MANAGED )
static void unspecified_bool( this_type*** )
{
}
typedef void (*unspecified_bool_type)( this_type*** );
operator unspecified_bool_type() const // never throws
{
return px == 0? 0: unspecified_bool;
}
#elif \
( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \
( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \
( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) )
typedef T * (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const // never throws
{
return px == 0? 0: &this_type::get;
}
#else
typedef T * this_type::*unspecified_bool_type;
operator unspecified_bool_type() const // never throws
{
return px == 0? 0: &this_type::px;
}
#endif
// operator! is redundant, but some compilers need it
bool operator! () const // never throws
{
return px == 0;
}

View File

@@ -0,0 +1,199 @@
#ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/quick_allocator.hpp
//
// Copyright (c) 2003 David Abrahams
// Copyright (c) 2003 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/lightweight_mutex.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <new> // ::operator new, ::operator delete
#include <cstddef> // std::size_t
namespace boost
{
namespace detail
{
template<unsigned size, unsigned align_> union freeblock
{
typedef typename boost::type_with_alignment<align_>::type aligner_type;
aligner_type aligner;
char bytes[size];
freeblock * next;
};
template<unsigned size, unsigned align_> struct allocator_impl
{
typedef freeblock<size, align_> block;
// It may seem odd to use such small pages.
//
// However, on a typical Windows implementation that uses
// the OS allocator, "normal size" pages interact with the
// "ordinary" operator new, slowing it down dramatically.
//
// 512 byte pages are handled by the small object allocator,
// and don't interfere with ::new.
//
// The other alternative is to use much bigger pages (1M.)
//
// It is surprisingly easy to hit pathological behavior by
// varying the page size. g++ 2.96 on Red Hat Linux 7.2,
// for example, passionately dislikes 496. 512 seems OK.
#if defined(BOOST_QA_PAGE_SIZE)
enum { items_per_page = BOOST_QA_PAGE_SIZE / size };
#else
enum { items_per_page = 512 / size }; // 1048560 / size
#endif
#ifdef BOOST_HAS_THREADS
static lightweight_mutex & mutex()
{
static freeblock< sizeof( lightweight_mutex ), boost::alignment_of< lightweight_mutex >::value > fbm;
static lightweight_mutex * pm = new( &fbm ) lightweight_mutex;
return *pm;
}
static lightweight_mutex * mutex_init;
#endif
static block * free;
static block * page;
static unsigned last;
static inline void * alloc()
{
#ifdef BOOST_HAS_THREADS
lightweight_mutex::scoped_lock lock( mutex() );
#endif
if(block * x = free)
{
free = x->next;
return x;
}
else
{
if(last == items_per_page)
{
// "Listen to me carefully: there is no memory leak"
// -- Scott Meyers, Eff C++ 2nd Ed Item 10
page = ::new block[items_per_page];
last = 0;
}
return &page[last++];
}
}
static inline void * alloc(std::size_t n)
{
if(n != size) // class-specific new called for a derived object
{
return ::operator new(n);
}
else
{
#ifdef BOOST_HAS_THREADS
lightweight_mutex::scoped_lock lock( mutex() );
#endif
if(block * x = free)
{
free = x->next;
return x;
}
else
{
if(last == items_per_page)
{
page = ::new block[items_per_page];
last = 0;
}
return &page[last++];
}
}
}
static inline void dealloc(void * pv)
{
if(pv != 0) // 18.4.1.1/13
{
#ifdef BOOST_HAS_THREADS
lightweight_mutex::scoped_lock lock( mutex() );
#endif
block * pb = static_cast<block *>(pv);
pb->next = free;
free = pb;
}
}
static inline void dealloc(void * pv, std::size_t n)
{
if(n != size) // class-specific delete called for a derived object
{
::operator delete(pv);
}
else if(pv != 0) // 18.4.1.1/13
{
#ifdef BOOST_HAS_THREADS
lightweight_mutex::scoped_lock lock( mutex() );
#endif
block * pb = static_cast<block *>(pv);
pb->next = free;
free = pb;
}
}
};
#ifdef BOOST_HAS_THREADS
template<unsigned size, unsigned align_>
lightweight_mutex * allocator_impl<size, align_>::mutex_init = &allocator_impl<size, align_>::mutex();
#endif
template<unsigned size, unsigned align_>
freeblock<size, align_> * allocator_impl<size, align_>::free = 0;
template<unsigned size, unsigned align_>
freeblock<size, align_> * allocator_impl<size, align_>::page = 0;
template<unsigned size, unsigned align_>
unsigned allocator_impl<size, align_>::last = allocator_impl<size, align_>::items_per_page;
template<class T>
struct quick_allocator: public allocator_impl< sizeof(T), boost::alignment_of<T>::value >
{
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED

View File

@@ -0,0 +1,151 @@
#ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED
//
// detail/shared_array_nmt.hpp - shared_array.hpp without member templates
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation.
//
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/detail/atomic_count.hpp>
#include <cstddef> // for std::ptrdiff_t
#include <algorithm> // for std::swap
#include <functional> // for std::less
#include <new> // for std::bad_alloc
namespace boost
{
template<class T> class shared_array
{
private:
typedef detail::atomic_count count_type;
public:
typedef T element_type;
explicit shared_array(T * p = 0): px(p)
{
#ifndef BOOST_NO_EXCEPTIONS
try // prevent leak if new throws
{
pn = new count_type(1);
}
catch(...)
{
boost::checked_array_delete(p);
throw;
}
#else
pn = new count_type(1);
if(pn == 0)
{
boost::checked_array_delete(p);
boost::throw_exception(std::bad_alloc());
}
#endif
}
~shared_array()
{
if(--*pn == 0)
{
boost::checked_array_delete(px);
delete pn;
}
}
shared_array(shared_array const & r) : px(r.px) // never throws
{
pn = r.pn;
++*pn;
}
shared_array & operator=(shared_array const & r)
{
shared_array(r).swap(*this);
return *this;
}
void reset(T * p = 0)
{
BOOST_ASSERT(p == 0 || p != px);
shared_array(p).swap(*this);
}
T * get() const // never throws
{
return px;
}
T & operator[](std::ptrdiff_t i) const // never throws
{
BOOST_ASSERT(px != 0);
BOOST_ASSERT(i >= 0);
return px[i];
}
long use_count() const // never throws
{
return *pn;
}
bool unique() const // never throws
{
return *pn == 1;
}
void swap(shared_array<T> & other) // never throws
{
std::swap(px, other.px);
std::swap(pn, other.pn);
}
private:
T * px; // contained pointer
count_type * pn; // ptr to reference counter
}; // shared_array
template<class T, class U> inline bool operator==(shared_array<T> const & a, shared_array<U> const & b)
{
return a.get() == b.get();
}
template<class T, class U> inline bool operator!=(shared_array<T> const & a, shared_array<U> const & b)
{
return a.get() != b.get();
}
template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b)
{
return std::less<T*>()(a.get(), b.get());
}
template<class T> void swap(shared_array<T> & a, shared_array<T> & b)
{
a.swap(b);
}
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_ARRAY_NMT_HPP_INCLUDED

View File

@@ -0,0 +1,444 @@
#ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/shared_count.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifdef __BORLANDC__
# pragma warn -8027 // Functions containing try are not expanded inline
#endif
#include <boost/config.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/bad_weak_ptr.hpp>
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
#include <boost/smart_ptr/detail/sp_counted_impl.hpp>
#include <boost/detail/workaround.hpp>
// In order to avoid circular dependencies with Boost.TR1
// we make sure that our include of <memory> doesn't try to
// pull in the TR1 headers: that's why we use this header
// rather than including <memory> directly:
#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
#include <functional> // std::less
#include <new> // std::bad_alloc
namespace boost
{
namespace detail
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
int const shared_count_id = 0x2C35F101;
int const weak_count_id = 0x298C38A4;
#endif
struct sp_nothrow_tag {};
class weak_count;
class shared_count
{
private:
sp_counted_base * pi_;
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
int id_;
#endif
friend class weak_count;
public:
shared_count(): pi_(0) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
}
template<class Y> explicit shared_count( Y * p ): pi_( 0 )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
#ifndef BOOST_NO_EXCEPTIONS
try
{
pi_ = new sp_counted_impl_p<Y>( p );
}
catch(...)
{
boost::checked_delete( p );
throw;
}
#else
pi_ = new sp_counted_impl_p<Y>( p );
if( pi_ == 0 )
{
boost::checked_delete( p );
boost::throw_exception( std::bad_alloc() );
}
#endif
}
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
template<class Y, class D> shared_count( Y * p, D d ): pi_(0)
#else
template<class P, class D> shared_count( P p, D d ): pi_(0)
#endif
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1200 )
typedef Y* P;
#endif
#ifndef BOOST_NO_EXCEPTIONS
try
{
pi_ = new sp_counted_impl_pd<P, D>(p, d);
}
catch(...)
{
d(p); // delete p
throw;
}
#else
pi_ = new sp_counted_impl_pd<P, D>(p, d);
if(pi_ == 0)
{
d(p); // delete p
boost::throw_exception(std::bad_alloc());
}
#endif
}
template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
typedef sp_counted_impl_pda<P, D, A> impl_type;
typedef typename A::template rebind< impl_type >::other A2;
A2 a2( a );
#ifndef BOOST_NO_EXCEPTIONS
try
{
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
}
catch(...)
{
d( p );
if( pi_ != 0 )
{
a2.deallocate( static_cast< impl_type* >( pi_ ), 1 );
}
throw;
}
#else
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
if( pi_ != 0 )
{
new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
}
else
{
d( p );
boost::throw_exception( std::bad_alloc() );
}
#endif
}
#ifndef BOOST_NO_AUTO_PTR
// auto_ptr<Y> is special cased to provide the strong guarantee
template<class Y>
explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
#ifdef BOOST_NO_EXCEPTIONS
if( pi_ == 0 )
{
boost::throw_exception(std::bad_alloc());
}
#endif
r.release();
}
#endif
~shared_count() // nothrow
{
if( pi_ != 0 ) pi_->release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
id_ = 0;
#endif
}
shared_count(shared_count const & r): pi_(r.pi_) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
if( pi_ != 0 ) pi_->add_ref_copy();
}
#if defined( BOOST_HAS_RVALUE_REFS )
shared_count(shared_count && r): pi_(r.pi_) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
r.pi_ = 0;
}
#endif
explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0
shared_count & operator= (shared_count const & r) // nothrow
{
sp_counted_base * tmp = r.pi_;
if( tmp != pi_ )
{
if( tmp != 0 ) tmp->add_ref_copy();
if( pi_ != 0 ) pi_->release();
pi_ = tmp;
}
return *this;
}
void swap(shared_count & r) // nothrow
{
sp_counted_base * tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
long use_count() const // nothrow
{
return pi_ != 0? pi_->use_count(): 0;
}
bool unique() const // nothrow
{
return use_count() == 1;
}
bool empty() const // nothrow
{
return pi_ == 0;
}
friend inline bool operator==(shared_count const & a, shared_count const & b)
{
return a.pi_ == b.pi_;
}
friend inline bool operator<(shared_count const & a, shared_count const & b)
{
return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
}
void * get_deleter( sp_typeinfo const & ti ) const
{
return pi_? pi_->get_deleter( ti ): 0;
}
};
class weak_count
{
private:
sp_counted_base * pi_;
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
int id_;
#endif
friend class shared_count;
public:
weak_count(): pi_(0) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
{
}
weak_count(shared_count const & r): pi_(r.pi_) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
{
if(pi_ != 0) pi_->weak_add_ref();
}
weak_count(weak_count const & r): pi_(r.pi_) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
{
if(pi_ != 0) pi_->weak_add_ref();
}
// Move support
#if defined( BOOST_HAS_RVALUE_REFS )
weak_count(weak_count && r): pi_(r.pi_) // nothrow
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
{
r.pi_ = 0;
}
#endif
~weak_count() // nothrow
{
if(pi_ != 0) pi_->weak_release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
id_ = 0;
#endif
}
weak_count & operator= (shared_count const & r) // nothrow
{
sp_counted_base * tmp = r.pi_;
if( tmp != pi_ )
{
if(tmp != 0) tmp->weak_add_ref();
if(pi_ != 0) pi_->weak_release();
pi_ = tmp;
}
return *this;
}
weak_count & operator= (weak_count const & r) // nothrow
{
sp_counted_base * tmp = r.pi_;
if( tmp != pi_ )
{
if(tmp != 0) tmp->weak_add_ref();
if(pi_ != 0) pi_->weak_release();
pi_ = tmp;
}
return *this;
}
void swap(weak_count & r) // nothrow
{
sp_counted_base * tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
long use_count() const // nothrow
{
return pi_ != 0? pi_->use_count(): 0;
}
bool empty() const // nothrow
{
return pi_ == 0;
}
friend inline bool operator==(weak_count const & a, weak_count const & b)
{
return a.pi_ == b.pi_;
}
friend inline bool operator<(weak_count const & a, weak_count const & b)
{
return std::less<sp_counted_base *>()(a.pi_, b.pi_);
}
};
inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
if( pi_ == 0 || !pi_->add_ref_lock() )
{
boost::throw_exception( boost::bad_weak_ptr() );
}
}
inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
if( pi_ != 0 && !pi_->add_ref_lock() )
{
pi_ = 0;
}
}
} // namespace detail
} // namespace boost
#ifdef __BORLANDC__
# pragma warn .8027 // Functions containing try are not expanded inline
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_COUNT_HPP_INCLUDED

View File

@@ -0,0 +1,182 @@
#ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED
//
// detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
//
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/detail/atomic_count.hpp>
#ifndef BOOST_NO_AUTO_PTR
# include <memory> // for std::auto_ptr
#endif
#include <algorithm> // for std::swap
#include <functional> // for std::less
#include <new> // for std::bad_alloc
namespace boost
{
template<class T> class shared_ptr
{
private:
typedef detail::atomic_count count_type;
public:
typedef T element_type;
typedef T value_type;
explicit shared_ptr(T * p = 0): px(p)
{
#ifndef BOOST_NO_EXCEPTIONS
try // prevent leak if new throws
{
pn = new count_type(1);
}
catch(...)
{
boost::checked_delete(p);
throw;
}
#else
pn = new count_type(1);
if(pn == 0)
{
boost::checked_delete(p);
boost::throw_exception(std::bad_alloc());
}
#endif
}
~shared_ptr()
{
if(--*pn == 0)
{
boost::checked_delete(px);
delete pn;
}
}
shared_ptr(shared_ptr const & r): px(r.px) // never throws
{
pn = r.pn;
++*pn;
}
shared_ptr & operator=(shared_ptr const & r)
{
shared_ptr(r).swap(*this);
return *this;
}
#ifndef BOOST_NO_AUTO_PTR
explicit shared_ptr(std::auto_ptr<T> & r)
{
pn = new count_type(1); // may throw
px = r.release(); // fix: moved here to stop leak if new throws
}
shared_ptr & operator=(std::auto_ptr<T> & r)
{
shared_ptr(r).swap(*this);
return *this;
}
#endif
void reset(T * p = 0)
{
BOOST_ASSERT(p == 0 || p != px);
shared_ptr(p).swap(*this);
}
T & operator*() const // never throws
{
BOOST_ASSERT(px != 0);
return *px;
}
T * operator->() const // never throws
{
BOOST_ASSERT(px != 0);
return px;
}
T * get() const // never throws
{
return px;
}
long use_count() const // never throws
{
return *pn;
}
bool unique() const // never throws
{
return *pn == 1;
}
void swap(shared_ptr<T> & other) // never throws
{
std::swap(px, other.px);
std::swap(pn, other.pn);
}
private:
T * px; // contained pointer
count_type * pn; // ptr to reference counter
};
template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
{
return a.get() == b.get();
}
template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
{
return a.get() != b.get();
}
template<class T> inline bool operator<(shared_ptr<T> const & a, shared_ptr<T> const & b)
{
return std::less<T*>()(a.get(), b.get());
}
template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b)
{
a.swap(b);
}
// get_pointer() enables boost::mem_fn to recognize shared_ptr
template<class T> inline T * get_pointer(shared_ptr<T> const & p)
{
return p.get();
}
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SHARED_PTR_NMT_HPP_INCLUDED

View File

@@ -0,0 +1,76 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// detail/sp_convertible.hpp
//
// Copyright 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( BOOST_NO_SFINAE )
# define BOOST_SP_NO_SP_CONVERTIBLE
#endif
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ < 303 )
# define BOOST_SP_NO_SP_CONVERTIBLE
#endif
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && defined( __BORLANDC__ ) && ( __BORLANDC__ <= 0x620 )
# define BOOST_SP_NO_SP_CONVERTIBLE
#endif
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
namespace boost
{
namespace detail
{
template< class Y, class T > struct sp_convertible
{
typedef char (&yes) [1];
typedef char (&no) [2];
static yes f( T* );
static no f( ... );
enum _vt { value = sizeof( f( static_cast<Y*>(0) ) ) == sizeof(yes) };
};
struct sp_empty
{
};
template< bool > struct sp_enable_if_convertible_impl;
template<> struct sp_enable_if_convertible_impl<true>
{
typedef sp_empty type;
};
template<> struct sp_enable_if_convertible_impl<false>
{
};
template< class Y, class T > struct sp_enable_if_convertible: public sp_enable_if_convertible_impl< sp_convertible< Y, T >::value >
{
};
} // namespace detail
} // namespace boost
#endif // !defined( BOOST_SP_NO_SP_CONVERTIBLE )
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_CONVERTIBLE_HPP_INCLUDED

View File

@@ -0,0 +1,70 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base.hpp
//
// Copyright 2005, 2006 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
#if defined( BOOST_SP_DISABLE_THREADS )
# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
#elif defined( BOOST_SP_USE_SPINLOCK )
# include <boost/smart_ptr/detail/sp_counted_base_spin.hpp>
#elif defined( BOOST_SP_USE_PTHREADS )
# include <boost/smart_ptr/detail/sp_counted_base_pt.hpp>
#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 )
# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
# include <boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp>
#elif defined( __GNUC__ ) && defined( __ia64__ ) && !defined( __INTEL_COMPILER )
# include <boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp>
#elif defined(__HP_aCC) && defined(__ia64)
# include <boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp>
#elif defined( __MWERKS__ ) && defined( __POWERPC__ )
# include <boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp>
#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) )
# include <boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp>
#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) )
# include <boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp>
#elif defined( BOOST_SP_HAS_SYNC )
# include <boost/smart_ptr/detail/sp_counted_base_sync.hpp>
#elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) )
# include <boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp>
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined(__CYGWIN__)
# include <boost/smart_ptr/detail/sp_counted_base_w32.hpp>
#elif !defined( BOOST_HAS_THREADS )
# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
#else
# include <boost/smart_ptr/detail/sp_counted_base_spin.hpp>
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED

View File

@@ -0,0 +1,150 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED
//
// detail/sp_counted_base_acc_ia64.hpp - aC++ on HP-UX IA64
//
// Copyright 2007 Baruch Zilber
// Copyright 2007 Boris Gubenko
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
#include <boost/detail/sp_typeinfo.hpp>
#include <machine/sys/inline.h>
namespace boost
{
namespace detail
{
inline void atomic_increment( int * pw )
{
// ++*pw;
_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, +1, _LDHINT_NONE);
}
inline int atomic_decrement( int * pw )
{
// return --*pw;
int r = static_cast<int>(_Asm_fetchadd(_FASZ_W, _SEM_REL, pw, -1, _LDHINT_NONE));
if (1 == r)
{
_Asm_mf();
}
return r - 1;
}
inline int atomic_conditional_increment( int * pw )
{
// if( *pw != 0 ) ++*pw;
// return *pw;
int v = *pw;
for (;;)
{
if (0 == v)
{
return 0;
}
_Asm_mov_to_ar(_AREG_CCV,
v,
(_UP_CALL_FENCE | _UP_SYS_FENCE | _DOWN_CALL_FENCE | _DOWN_SYS_FENCE));
int r = static_cast<int>(_Asm_cmpxchg(_SZ_W, _SEM_ACQ, pw, v + 1, _LDHINT_NONE));
if (r == v)
{
return r + 1;
}
v = r;
}
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_decrement( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_decrement( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<int const volatile &>( use_count_ ); // TODO use ld.acq here
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_ACC_IA64_HPP_INCLUDED

View File

@@ -0,0 +1,170 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_cw_ppc.hpp - CodeWarrior on PowerPC
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
namespace boost
{
namespace detail
{
inline void atomic_increment( register long * pw )
{
register int a;
asm
{
loop:
lwarx a, 0, pw
addi a, a, 1
stwcx. a, 0, pw
bne- loop
}
}
inline long atomic_decrement( register long * pw )
{
register int a;
asm
{
sync
loop:
lwarx a, 0, pw
addi a, a, -1
stwcx. a, 0, pw
bne- loop
isync
}
return a;
}
inline long atomic_conditional_increment( register long * pw )
{
register int a;
asm
{
loop:
lwarx a, 0, pw
cmpwi a, 0
beq store
addi a, a, 1
store:
stwcx. a, 0, pw
bne- loop
}
return a;
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_decrement( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_decrement( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<long const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_PPC_HPP_INCLUDED

View File

@@ -0,0 +1,158 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_cw_x86.hpp - CodeWarrion on 486+
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
// Copyright 2005 Rene Rivera
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
namespace boost
{
namespace detail
{
inline int atomic_exchange_and_add( int * pw, int dv )
{
// int r = *pw;
// *pw += dv;
// return r;
asm
{
mov esi, [pw]
mov eax, dv
lock xadd dword ptr [esi], eax
}
}
inline void atomic_increment( int * pw )
{
//atomic_exchange_and_add( pw, 1 );
asm
{
mov esi, [pw]
lock inc dword ptr [esi]
}
}
inline int atomic_conditional_increment( int * pw )
{
// int rv = *pw;
// if( rv != 0 ) ++*pw;
// return rv;
asm
{
mov esi, [pw]
mov eax, dword ptr [esi]
L0:
test eax, eax
je L1
mov ebx, eax
inc ebx
lock cmpxchg dword ptr [esi], ebx
jne L0
L1:
}
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<int const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED

View File

@@ -0,0 +1,157 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED
//
// detail/sp_counted_base_gcc_ia64.hpp - g++ on IA64
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2006 Peter Dimov
// Copyright 2005 Ben Hutchings
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
#include <boost/detail/sp_typeinfo.hpp>
namespace boost
{
namespace detail
{
inline void atomic_increment( int * pw )
{
// ++*pw;
int tmp;
// No barrier is required here but fetchadd always has an acquire or
// release barrier associated with it. We choose release as it should be
// cheaper.
__asm__ ("fetchadd4.rel %0=%1,1" :
"=r"(tmp), "=m"(*pw) :
"m"( *pw ));
}
inline int atomic_decrement( int * pw )
{
// return --*pw;
int rv;
__asm__ (" fetchadd4.rel %0=%1,-1 ;; \n"
" cmp.eq p7,p0=1,%0 ;; \n"
"(p7) ld4.acq %0=%1 " :
"=&r"(rv), "=m"(*pw) :
"m"( *pw ) :
"p7");
return rv;
}
inline int atomic_conditional_increment( int * pw )
{
// if( *pw != 0 ) ++*pw;
// return *pw;
int rv, tmp, tmp2;
__asm__ ("0: ld4 %0=%3 ;; \n"
" cmp.eq p7,p0=0,%0 ;; \n"
"(p7) br.cond.spnt 1f \n"
" mov ar.ccv=%0 \n"
" add %1=1,%0 ;; \n"
" cmpxchg4.acq %2=%3,%1,ar.ccv ;; \n"
" cmp.ne p7,p0=%0,%2 ;; \n"
"(p7) br.cond.spnt 0b \n"
" mov %0=%1 ;; \n"
"1:" :
"=&r"(rv), "=&r"(tmp), "=&r"(tmp2), "=m"(*pw) :
"m"( *pw ) :
"ar.ccv", "p7");
return rv;
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_decrement( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_decrement( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<int const volatile &>( use_count_ ); // TODO use ld.acq here
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_IA64_HPP_INCLUDED

View File

@@ -0,0 +1,172 @@
#ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED
#define BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_gcc_mips.hpp - g++ on MIPS
//
// Copyright (c) 2009, Spirent Communications, Inc.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
#include <boost/detail/sp_typeinfo.hpp>
namespace boost
{
namespace detail
{
inline void atomic_increment( int * pw )
{
// ++*pw;
int tmp;
__asm__ __volatile__
(
"0:\n\t"
"ll %0, %1\n\t"
"addiu %0, 1\n\t"
"sc %0, %1\n\t"
"beqz %0, 0b":
"=&r"( tmp ), "=m"( *pw ):
"m"( *pw )
);
}
inline int atomic_decrement( int * pw )
{
// return --*pw;
int rv, tmp;
__asm__ __volatile__
(
"0:\n\t"
"ll %1, %2\n\t"
"addiu %0, %1, -1\n\t"
"sc %0, %2\n\t"
"beqz %0, 0b\n\t"
"addiu %0, %1, -1":
"=&r"( rv ), "=&r"( tmp ), "=m"( *pw ):
"m"( *pw ):
"memory"
);
return rv;
}
inline int atomic_conditional_increment( int * pw )
{
// if( *pw != 0 ) ++*pw;
// return *pw;
int rv, tmp;
__asm__ __volatile__
(
"0:\n\t"
"ll %0, %2\n\t"
"beqz %0, 1f\n\t"
"addiu %1, %0, 1\n\t"
"sc %1, %2\n\t"
"beqz %1, 0b\n\t"
"addiu %0, %0, 1\n\t"
"1:":
"=&r"( rv ), "=&r"( tmp ), "=m"( *pw ):
"m"( *pw ):
"memory"
);
return rv;
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_decrement( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_decrement( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<int const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_DETAIL_SP_COUNTED_BASE_GCC_MIPS_HPP_INCLUDED

View File

@@ -0,0 +1,181 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_gcc_ppc.hpp - g++ on PowerPC
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
namespace boost
{
namespace detail
{
inline void atomic_increment( int * pw )
{
// ++*pw;
int tmp;
__asm__
(
"0:\n\t"
"lwarx %1, 0, %2\n\t"
"addi %1, %1, 1\n\t"
"stwcx. %1, 0, %2\n\t"
"bne- 0b":
"=m"( *pw ), "=&b"( tmp ):
"r"( pw ), "m"( *pw ):
"cc"
);
}
inline int atomic_decrement( int * pw )
{
// return --*pw;
int rv;
__asm__ __volatile__
(
"sync\n\t"
"0:\n\t"
"lwarx %1, 0, %2\n\t"
"addi %1, %1, -1\n\t"
"stwcx. %1, 0, %2\n\t"
"bne- 0b\n\t"
"isync":
"=m"( *pw ), "=&b"( rv ):
"r"( pw ), "m"( *pw ):
"memory", "cc"
);
return rv;
}
inline int atomic_conditional_increment( int * pw )
{
// if( *pw != 0 ) ++*pw;
// return *pw;
int rv;
__asm__
(
"0:\n\t"
"lwarx %1, 0, %2\n\t"
"cmpwi %1, 0\n\t"
"beq 1f\n\t"
"addi %1, %1, 1\n\t"
"1:\n\t"
"stwcx. %1, 0, %2\n\t"
"bne- 0b":
"=m"( *pw ), "=&b"( rv ):
"r"( pw ), "m"( *pw ):
"cc"
);
return rv;
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_decrement( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_decrement( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<int const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_PPC_HPP_INCLUDED

View File

@@ -0,0 +1,166 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// detail/sp_counted_base_gcc_sparc.hpp - g++ on Sparc V8+
//
// Copyright (c) 2006 Piotr Wyderski
// Copyright (c) 2006 Tomas Puverle
// Copyright (c) 2006 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// Thanks to Michael van der Westhuizen
#include <boost/detail/sp_typeinfo.hpp>
#include <inttypes.h> // int32_t
namespace boost
{
namespace detail
{
inline int32_t compare_and_swap( int32_t * dest_, int32_t compare_, int32_t swap_ )
{
__asm__ __volatile__( "cas [%1], %2, %0"
: "+r" (swap_)
: "r" (dest_), "r" (compare_)
: "memory" );
return swap_;
}
inline int32_t atomic_fetch_and_add( int32_t * pw, int32_t dv )
{
// long r = *pw;
// *pw += dv;
// return r;
for( ;; )
{
int32_t r = *pw;
if( __builtin_expect((compare_and_swap(pw, r, r + dv) == r), 1) )
{
return r;
}
}
}
inline void atomic_increment( int32_t * pw )
{
atomic_fetch_and_add( pw, 1 );
}
inline int32_t atomic_decrement( int32_t * pw )
{
return atomic_fetch_and_add( pw, -1 );
}
inline int32_t atomic_conditional_increment( int32_t * pw )
{
// long r = *pw;
// if( r != 0 ) ++*pw;
// return r;
for( ;; )
{
int32_t r = *pw;
if( r == 0 )
{
return r;
}
if( __builtin_expect( ( compare_and_swap( pw, r, r + 1 ) == r ), 1 ) )
{
return r;
}
}
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int32_t use_count_; // #shared
int32_t weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_decrement( &use_count_ ) == 1 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_decrement( &weak_count_ ) == 1 )
{
destroy();
}
}
long use_count() const // nothrow
{
return const_cast< int32_t const volatile & >( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_SPARC_HPP_INCLUDED

View File

@@ -0,0 +1,173 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_gcc_x86.hpp - g++ on 486+ or AMD64
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
namespace boost
{
namespace detail
{
inline int atomic_exchange_and_add( int * pw, int dv )
{
// int r = *pw;
// *pw += dv;
// return r;
int r;
__asm__ __volatile__
(
"lock\n\t"
"xadd %1, %0":
"=m"( *pw ), "=r"( r ): // outputs (%0, %1)
"m"( *pw ), "1"( dv ): // inputs (%2, %3 == %1)
"memory", "cc" // clobbers
);
return r;
}
inline void atomic_increment( int * pw )
{
//atomic_exchange_and_add( pw, 1 );
__asm__
(
"lock\n\t"
"incl %0":
"=m"( *pw ): // output (%0)
"m"( *pw ): // input (%1)
"cc" // clobbers
);
}
inline int atomic_conditional_increment( int * pw )
{
// int rv = *pw;
// if( rv != 0 ) ++*pw;
// return rv;
int rv, tmp;
__asm__
(
"movl %0, %%eax\n\t"
"0:\n\t"
"test %%eax, %%eax\n\t"
"je 1f\n\t"
"movl %%eax, %2\n\t"
"incl %2\n\t"
"lock\n\t"
"cmpxchgl %2, %0\n\t"
"jne 0b\n\t"
"1:":
"=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)
"m"( *pw ): // input (%3)
"cc" // clobbers
);
return rv;
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<int const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_X86_HPP_INCLUDED

View File

@@ -0,0 +1,107 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_nt.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/sp_typeinfo.hpp>
namespace boost
{
namespace detail
{
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
++use_count_;
}
bool add_ref_lock() // true on success
{
if( use_count_ == 0 ) return false;
++use_count_;
return true;
}
void release() // nothrow
{
if( --use_count_ == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
++weak_count_;
}
void weak_release() // nothrow
{
if( --weak_count_ == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return use_count_;
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_NT_HPP_INCLUDED

View File

@@ -0,0 +1,135 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_pt.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/sp_typeinfo.hpp>
#include <pthread.h>
namespace boost
{
namespace detail
{
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
mutable pthread_mutex_t m_;
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
// HPUX 10.20 / DCE has a nonstandard pthread_mutex_init
#if defined(__hpux) && defined(_DECTHREADS_)
pthread_mutex_init( &m_, pthread_mutexattr_default );
#else
pthread_mutex_init( &m_, 0 );
#endif
}
virtual ~sp_counted_base() // nothrow
{
pthread_mutex_destroy( &m_ );
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
pthread_mutex_lock( &m_ );
++use_count_;
pthread_mutex_unlock( &m_ );
}
bool add_ref_lock() // true on success
{
pthread_mutex_lock( &m_ );
bool r = use_count_ == 0? false: ( ++use_count_, true );
pthread_mutex_unlock( &m_ );
return r;
}
void release() // nothrow
{
pthread_mutex_lock( &m_ );
long new_use_count = --use_count_;
pthread_mutex_unlock( &m_ );
if( new_use_count == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
pthread_mutex_lock( &m_ );
++weak_count_;
pthread_mutex_unlock( &m_ );
}
void weak_release() // nothrow
{
pthread_mutex_lock( &m_ );
long new_weak_count = --weak_count_;
pthread_mutex_unlock( &m_ );
if( new_weak_count == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
pthread_mutex_lock( &m_ );
long r = use_count_;
pthread_mutex_unlock( &m_ );
return r;
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_PT_HPP_INCLUDED

View File

@@ -0,0 +1,113 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED
//
// detail/sp_counted_base_solaris.hpp
// based on: detail/sp_counted_base_w32.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
// Copyright 2006 Michael van der Westhuizen
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
#include <atomic.h>
namespace boost
{
namespace detail
{
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
uint32_t use_count_; // #shared
uint32_t weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
atomic_inc_32( &use_count_ );
}
bool add_ref_lock() // true on success
{
for( ;; )
{
uint32_t tmp = static_cast< uint32_t const volatile& >( use_count_ );
if( tmp == 0 ) return false;
if( atomic_cas_32( &use_count_, tmp, tmp + 1 ) == tmp ) return true;
}
}
void release() // nothrow
{
if( atomic_dec_32_nv( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_inc_32( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_dec_32_nv( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<long const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SOLARIS_HPP_INCLUDED

View File

@@ -0,0 +1,131 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_spin.hpp - spinlock pool atomic emulation
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/spinlock_pool.hpp>
namespace boost
{
namespace detail
{
inline int atomic_exchange_and_add( int * pw, int dv )
{
spinlock_pool<1>::scoped_lock lock( pw );
int r = *pw;
*pw += dv;
return r;
}
inline void atomic_increment( int * pw )
{
spinlock_pool<1>::scoped_lock lock( pw );
++*pw;
}
inline int atomic_conditional_increment( int * pw )
{
spinlock_pool<1>::scoped_lock lock( pw );
int rv = *pw;
if( rv != 0 ) ++*pw;
return rv;
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
{
destroy();
}
}
long use_count() const // nothrow
{
spinlock_pool<1>::scoped_lock lock( &use_count_ );
return use_count_;
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SPIN_HPP_INCLUDED

View File

@@ -0,0 +1,155 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// detail/sp_counted_base_sync.hpp - g++ 4.1+ __sync intrinsics
//
// Copyright (c) 2007 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/sp_typeinfo.hpp>
#include <limits.h>
#if defined( __ia64__ ) && defined( __INTEL_COMPILER )
# include <ia64intrin.h>
#endif
namespace boost
{
namespace detail
{
#if INT_MAX >= 2147483647
typedef int sp_int32_t;
#else
typedef long sp_int32_t;
#endif
inline void atomic_increment( sp_int32_t * pw )
{
__sync_fetch_and_add( pw, 1 );
}
inline sp_int32_t atomic_decrement( sp_int32_t * pw )
{
return __sync_fetch_and_add( pw, -1 );
}
inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw )
{
// long r = *pw;
// if( r != 0 ) ++*pw;
// return r;
sp_int32_t r = *pw;
for( ;; )
{
if( r == 0 )
{
return r;
}
sp_int32_t r2 = __sync_val_compare_and_swap( pw, r, r + 1 );
if( r2 == r )
{
return r;
}
else
{
r = r2;
}
}
}
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
sp_int32_t use_count_; // #shared
sp_int32_t weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
{
if( atomic_decrement( &use_count_ ) == 1 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
{
if( atomic_decrement( &weak_count_ ) == 1 )
{
destroy();
}
}
long use_count() const // nothrow
{
return const_cast< sp_int32_t const volatile & >( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED

View File

@@ -0,0 +1,130 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_base_w32.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
#include <boost/detail/interlocked.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/detail/sp_typeinfo.hpp>
namespace boost
{
namespace detail
{
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
long weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
void add_ref_copy()
{
BOOST_INTERLOCKED_INCREMENT( &use_count_ );
}
bool add_ref_lock() // true on success
{
for( ;; )
{
long tmp = static_cast< long const volatile& >( use_count_ );
if( tmp == 0 ) return false;
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 )
// work around a code generation bug
long tmp2 = tmp + 1;
if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true;
#else
if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true;
#endif
}
}
void release() // nothrow
{
if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
{
dispose();
weak_release();
}
}
void weak_add_ref() // nothrow
{
BOOST_INTERLOCKED_INCREMENT( &weak_count_ );
}
void weak_release() // nothrow
{
if( BOOST_INTERLOCKED_DECREMENT( &weak_count_ ) == 0 )
{
destroy();
}
}
long use_count() const // nothrow
{
return static_cast<long const volatile &>( use_count_ );
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_W32_HPP_INCLUDED

View File

@@ -0,0 +1,231 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// detail/sp_counted_impl.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/config.hpp>
#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
#endif
#include <boost/checked_delete.hpp>
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
#include <boost/smart_ptr/detail/quick_allocator.hpp>
#endif
#if defined(BOOST_SP_USE_STD_ALLOCATOR)
#include <memory> // std::allocator
#endif
#include <cstddef> // std::size_t
namespace boost
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
void sp_scalar_constructor_hook( void * px, std::size_t size, void * pn );
void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn );
#endif
namespace detail
{
template<class X> class sp_counted_impl_p: public sp_counted_base
{
private:
X * px_;
sp_counted_impl_p( sp_counted_impl_p const & );
sp_counted_impl_p & operator= ( sp_counted_impl_p const & );
typedef sp_counted_impl_p<X> this_type;
public:
explicit sp_counted_impl_p( X * px ): px_( px )
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_constructor_hook( px, sizeof(X), this );
#endif
}
virtual void dispose() // nothrow
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_destructor_hook( px_, sizeof(X), this );
#endif
boost::checked_delete( px_ );
}
virtual void * get_deleter( detail::sp_typeinfo const & )
{
return 0;
}
#if defined(BOOST_SP_USE_STD_ALLOCATOR)
void * operator new( std::size_t )
{
return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );
}
void operator delete( void * p )
{
std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );
}
#endif
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
void * operator new( std::size_t )
{
return quick_allocator<this_type>::alloc();
}
void operator delete( void * p )
{
quick_allocator<this_type>::dealloc( p );
}
#endif
};
//
// Borland's Codeguard trips up over the -Vx- option here:
//
#ifdef __CODEGUARD__
# pragma option push -Vx-
#endif
template<class P, class D> class sp_counted_impl_pd: public sp_counted_base
{
private:
P ptr; // copy constructor must not throw
D del; // copy constructor must not throw
sp_counted_impl_pd( sp_counted_impl_pd const & );
sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
typedef sp_counted_impl_pd<P, D> this_type;
public:
// pre: d(p) must not throw
sp_counted_impl_pd( P p, D d ): ptr(p), del(d)
{
}
virtual void dispose() // nothrow
{
del( ptr );
}
virtual void * get_deleter( detail::sp_typeinfo const & ti )
{
return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
}
#if defined(BOOST_SP_USE_STD_ALLOCATOR)
void * operator new( std::size_t )
{
return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) );
}
void operator delete( void * p )
{
std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 );
}
#endif
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
void * operator new( std::size_t )
{
return quick_allocator<this_type>::alloc();
}
void operator delete( void * p )
{
quick_allocator<this_type>::dealloc( p );
}
#endif
};
template<class P, class D, class A> class sp_counted_impl_pda: public sp_counted_base
{
private:
P p_; // copy constructor must not throw
D d_; // copy constructor must not throw
A a_; // copy constructor must not throw
sp_counted_impl_pda( sp_counted_impl_pda const & );
sp_counted_impl_pda & operator= ( sp_counted_impl_pda const & );
typedef sp_counted_impl_pda<P, D, A> this_type;
public:
// pre: d( p ) must not throw
sp_counted_impl_pda( P p, D d, A a ): p_( p ), d_( d ), a_( a )
{
}
virtual void dispose() // nothrow
{
d_( p_ );
}
virtual void destroy() // nothrow
{
typedef typename A::template rebind< this_type >::other A2;
A2 a2( a_ );
this->~this_type();
a2.deallocate( this, 1 );
}
virtual void * get_deleter( detail::sp_typeinfo const & ti )
{
return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;
}
};
#ifdef __CODEGUARD__
# pragma option pop
#endif
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED

View File

@@ -0,0 +1,49 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/smart_ptr/detail/sp_has_sync.hpp
//
// Copyright (c) 2008, 2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Defines the BOOST_SP_HAS_SYNC macro if the __sync_* intrinsics
// are available.
//
#if defined(__GNUC__) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
#define BOOST_SP_HAS_SYNC
#if defined( __arm__ ) || defined( __armel__ )
#undef BOOST_SP_HAS_SYNC
#endif
#if defined( __hppa ) || defined( __hppa__ )
#undef BOOST_SP_HAS_SYNC
#endif
#if defined( __m68k__ )
#undef BOOST_SP_HAS_SYNC
#endif
#if defined( __sparc__ )
#undef BOOST_SP_HAS_SYNC
#endif
#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) && ( __INTEL_COMPILER < 1100 )
#undef BOOST_SP_HAS_SYNC
#endif
#endif // __GNUC__ * 100 + __GNUC_MINOR__ >= 401
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_HPP_INCLUDED

View File

@@ -0,0 +1,53 @@
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/detail/spinlock.hpp
//
// Copyright (c) 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// struct spinlock
// {
// void lock();
// bool try_lock();
// void unlock();
//
// class scoped_lock;
// };
//
// #define BOOST_DETAIL_SPINLOCK_INIT <unspecified>
//
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
#if defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ )
# include <boost/smart_ptr/detail/spinlock_gcc_arm.hpp>
#elif defined( BOOST_SP_HAS_SYNC )
# include <boost/smart_ptr/detail/spinlock_sync.hpp>
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# include <boost/smart_ptr/detail/spinlock_w32.hpp>
#elif defined(BOOST_HAS_PTHREADS)
# include <boost/smart_ptr/detail/spinlock_pt.hpp>
#elif !defined(BOOST_HAS_THREADS)
# include <boost/smart_ptr/detail/spinlock_nt.hpp>
#else
# error Unrecognized threading platform
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_HPP_INCLUDED

View File

@@ -0,0 +1,85 @@
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED
//
// Copyright (c) 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/smart_ptr/detail/yield_k.hpp>
namespace boost
{
namespace detail
{
class spinlock
{
public:
int v_;
public:
bool try_lock()
{
int r;
__asm__ __volatile__(
"swp %0, %1, [%2]":
"=&r"( r ): // outputs
"r"( 1 ), "r"( &v_ ): // inputs
"memory", "cc" );
return r == 0;
}
void lock()
{
for( unsigned k = 0; !try_lock(); ++k )
{
boost::detail::yield( k );
}
}
void unlock()
{
__asm__ __volatile__( "" ::: "memory" );
*const_cast< int volatile* >( &v_ ) = 0;
}
public:
class scoped_lock
{
private:
spinlock & sp_;
scoped_lock( scoped_lock const & );
scoped_lock & operator=( scoped_lock const & );
public:
explicit scoped_lock( spinlock & sp ): sp_( sp )
{
sp.lock();
}
~scoped_lock()
{
sp_.unlock();
}
};
};
} // namespace detail
} // namespace boost
#define BOOST_DETAIL_SPINLOCK_INIT {0}
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ARM_HPP_INCLUDED

View File

@@ -0,0 +1,89 @@
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// Copyright (c) 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/assert.hpp>
namespace boost
{
namespace detail
{
class spinlock
{
public:
bool locked_;
public:
inline bool try_lock()
{
if( locked_ )
{
return false;
}
else
{
locked_ = true;
return true;
}
}
inline void lock()
{
BOOST_ASSERT( !locked_ );
locked_ = true;
}
inline void unlock()
{
BOOST_ASSERT( locked_ );
locked_ = false;
}
public:
class scoped_lock
{
private:
spinlock & sp_;
scoped_lock( scoped_lock const & );
scoped_lock & operator=( scoped_lock const & );
public:
explicit scoped_lock( spinlock & sp ): sp_( sp )
{
sp.lock();
}
~scoped_lock()
{
sp_.unlock();
}
};
};
} // namespace detail
} // namespace boost
#define BOOST_DETAIL_SPINLOCK_INIT { false }
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_NT_HPP_INCLUDED

View File

@@ -0,0 +1,87 @@
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/detail/spinlock_pool.hpp
//
// Copyright (c) 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// spinlock_pool<0> is reserved for atomic<>, when/if it arrives
// spinlock_pool<1> is reserved for shared_ptr reference counts
// spinlock_pool<2> is reserved for shared_ptr atomic access
//
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/spinlock.hpp>
#include <cstddef>
namespace boost
{
namespace detail
{
template< int I > class spinlock_pool
{
private:
static spinlock pool_[ 41 ];
public:
static spinlock & spinlock_for( void const * pv )
{
std::size_t i = reinterpret_cast< std::size_t >( pv ) % 41;
return pool_[ i ];
}
class scoped_lock
{
private:
spinlock & sp_;
scoped_lock( scoped_lock const & );
scoped_lock & operator=( scoped_lock const & );
public:
explicit scoped_lock( void const * pv ): sp_( spinlock_for( pv ) )
{
sp_.lock();
}
~scoped_lock()
{
sp_.unlock();
}
};
};
template< int I > spinlock spinlock_pool< I >::pool_[ 41 ] =
{
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT, BOOST_DETAIL_SPINLOCK_INIT,
BOOST_DETAIL_SPINLOCK_INIT
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_POOL_HPP_INCLUDED

View File

@@ -0,0 +1,79 @@
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// Copyright (c) 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <pthread.h>
namespace boost
{
namespace detail
{
class spinlock
{
public:
pthread_mutex_t v_;
public:
bool try_lock()
{
return pthread_mutex_trylock( &v_ ) == 0;
}
void lock()
{
pthread_mutex_lock( &v_ );
}
void unlock()
{
pthread_mutex_unlock( &v_ );
}
public:
class scoped_lock
{
private:
spinlock & sp_;
scoped_lock( scoped_lock const & );
scoped_lock & operator=( scoped_lock const & );
public:
explicit scoped_lock( spinlock & sp ): sp_( sp )
{
sp.lock();
}
~scoped_lock()
{
sp_.unlock();
}
};
};
} // namespace detail
} // namespace boost
#define BOOST_DETAIL_SPINLOCK_INIT { PTHREAD_MUTEX_INITIALIZER }
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_PT_HPP_INCLUDED

View File

@@ -0,0 +1,87 @@
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// Copyright (c) 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/smart_ptr/detail/yield_k.hpp>
#if defined( __ia64__ ) && defined( __INTEL_COMPILER )
# include <ia64intrin.h>
#endif
namespace boost
{
namespace detail
{
class spinlock
{
public:
int v_;
public:
bool try_lock()
{
int r = __sync_lock_test_and_set( &v_, 1 );
return r == 0;
}
void lock()
{
for( unsigned k = 0; !try_lock(); ++k )
{
boost::detail::yield( k );
}
}
void unlock()
{
__sync_lock_release( &v_ );
}
public:
class scoped_lock
{
private:
spinlock & sp_;
scoped_lock( scoped_lock const & );
scoped_lock & operator=( scoped_lock const & );
public:
explicit scoped_lock( spinlock & sp ): sp_( sp )
{
sp.lock();
}
~scoped_lock()
{
sp_.unlock();
}
};
};
} // namespace detail
} // namespace boost
#define BOOST_DETAIL_SPINLOCK_INIT {0}
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_SYNC_HPP_INCLUDED

View File

@@ -0,0 +1,113 @@
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// Copyright (c) 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/interlocked.hpp>
#include <boost/smart_ptr/detail/yield_k.hpp>
// BOOST_COMPILER_FENCE
#if defined(__INTEL_COMPILER)
#define BOOST_COMPILER_FENCE __memory_barrier();
#elif defined( _MSC_VER ) && _MSC_VER >= 1310
extern "C" void _ReadWriteBarrier();
#pragma intrinsic( _ReadWriteBarrier )
#define BOOST_COMPILER_FENCE _ReadWriteBarrier();
#elif defined(__GNUC__)
#define BOOST_COMPILER_FENCE __asm__ __volatile__( "" : : : "memory" );
#else
#define BOOST_COMPILER_FENCE
#endif
//
namespace boost
{
namespace detail
{
class spinlock
{
public:
long v_;
public:
bool try_lock()
{
long r = BOOST_INTERLOCKED_EXCHANGE( &v_, 1 );
BOOST_COMPILER_FENCE
return r == 0;
}
void lock()
{
for( unsigned k = 0; !try_lock(); ++k )
{
boost::detail::yield( k );
}
}
void unlock()
{
BOOST_COMPILER_FENCE
*const_cast< long volatile* >( &v_ ) = 0;
}
public:
class scoped_lock
{
private:
spinlock & sp_;
scoped_lock( scoped_lock const & );
scoped_lock & operator=( scoped_lock const & );
public:
explicit scoped_lock( spinlock & sp ): sp_( sp )
{
sp.lock();
}
~scoped_lock()
{
sp_.unlock();
}
};
};
} // namespace detail
} // namespace boost
#define BOOST_DETAIL_SPINLOCK_INIT {0}
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_W32_HPP_INCLUDED

View File

@@ -0,0 +1,149 @@
#ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// yield_k.hpp
//
// Copyright (c) 2008 Peter Dimov
//
// void yield( unsigned k );
//
// Typical use:
//
// for( unsigned k = 0; !try_lock(); ++k ) yield( k );
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/config.hpp>
// BOOST_SMT_PAUSE
#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) )
extern "C" void _mm_pause();
#pragma intrinsic( _mm_pause )
#define BOOST_SMT_PAUSE _mm_pause();
#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
#endif
//
#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
#endif
namespace boost
{
namespace detail
{
#if !defined( BOOST_USE_WINDOWS_H )
extern "C" void __stdcall Sleep( unsigned ms );
#endif
inline void yield( unsigned k )
{
if( k < 4 )
{
}
#if defined( BOOST_SMT_PAUSE )
else if( k < 16 )
{
BOOST_SMT_PAUSE
}
#endif
else if( k < 32 )
{
Sleep( 0 );
}
else
{
Sleep( 1 );
}
}
} // namespace detail
} // namespace boost
#elif defined( BOOST_HAS_PTHREADS )
#include <sched.h>
#include <time.h>
namespace boost
{
namespace detail
{
inline void yield( unsigned k )
{
if( k < 4 )
{
}
#if defined( BOOST_SMT_PAUSE )
else if( k < 16 )
{
BOOST_SMT_PAUSE
}
#endif
else if( k < 32 || k & 1 )
{
sched_yield();
}
else
{
// g++ -Wextra warns on {} or {0}
struct timespec rqtp = { 0, 0 };
// POSIX says that timespec has tv_sec and tv_nsec
// But it doesn't guarantee order or placement
rqtp.tv_sec = 0;
rqtp.tv_nsec = 1000;
nanosleep( &rqtp, 0 );
}
}
} // namespace detail
} // namespace boost
#else
namespace boost
{
namespace detail
{
inline void yield( unsigned )
{
}
} // namespace detail
} // namespace boost
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED

View File

@@ -0,0 +1,79 @@
#ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
#define BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED
//
// enable_shared_from_this.hpp
//
// Copyright 2002, 2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html
//
#include <boost/smart_ptr/weak_ptr.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
namespace boost
{
template<class T> class enable_shared_from_this
{
protected:
enable_shared_from_this()
{
}
enable_shared_from_this(enable_shared_from_this const &)
{
}
enable_shared_from_this & operator=(enable_shared_from_this const &)
{
return *this;
}
~enable_shared_from_this()
{
}
public:
shared_ptr<T> shared_from_this()
{
shared_ptr<T> p( weak_this_ );
BOOST_ASSERT( p.get() == this );
return p;
}
shared_ptr<T const> shared_from_this() const
{
shared_ptr<T const> p( weak_this_ );
BOOST_ASSERT( p.get() == this );
return p;
}
public: // actually private, but avoids compiler template friendship issues
// Note: invoked automatically by shared_ptr; do not call
template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const
{
if( weak_this_.expired() )
{
weak_this_ = shared_ptr<T>( *ppx, py );
}
}
private:
mutable weak_ptr<T> weak_this_;
};
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_ENABLE_SHARED_FROM_THIS_HPP_INCLUDED

View File

@@ -0,0 +1,132 @@
#ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED
#define BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED
//
// enable_shared_from_this2.hpp
//
// Copyright 2002, 2009 Peter Dimov
// Copyright 2008 Frank Mori Hess
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/config.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/assert.hpp>
#include <boost/detail/workaround.hpp>
namespace boost
{
namespace detail
{
class esft2_deleter_wrapper
{
private:
shared_ptr<void> deleter_;
public:
esft2_deleter_wrapper()
{
}
template< class T > void set_deleter( shared_ptr<T> const & deleter )
{
deleter_ = deleter;
}
template< class T> void operator()( T* )
{
BOOST_ASSERT( deleter_.use_count() <= 1 );
deleter_.reset();
}
};
} // namespace detail
template< class T > class enable_shared_from_this2
{
protected:
enable_shared_from_this2()
{
}
enable_shared_from_this2( enable_shared_from_this2 const & )
{
}
enable_shared_from_this2 & operator=( enable_shared_from_this2 const & )
{
return *this;
}
~enable_shared_from_this2()
{
BOOST_ASSERT( shared_this_.use_count() <= 1 ); // make sure no dangling shared_ptr objects exist
}
private:
mutable weak_ptr<T> weak_this_;
mutable shared_ptr<T> shared_this_;
public:
shared_ptr<T> shared_from_this()
{
init_weak_once();
return shared_ptr<T>( weak_this_ );
}
shared_ptr<T const> shared_from_this() const
{
init_weak_once();
return shared_ptr<T>( weak_this_ );
}
private:
void init_weak_once() const
{
if( weak_this_._empty() )
{
shared_this_.reset( static_cast< T* >( 0 ), detail::esft2_deleter_wrapper() );
weak_this_ = shared_this_;
}
}
public: // actually private, but avoids compiler template friendship issues
// Note: invoked automatically by shared_ptr; do not call
template<class X, class Y> void _internal_accept_owner( shared_ptr<X> * ppx, Y * py ) const
{
BOOST_ASSERT( ppx != 0 );
if( weak_this_.use_count() == 0 )
{
weak_this_ = shared_ptr<T>( *ppx, py );
}
else if( shared_this_.use_count() != 0 )
{
BOOST_ASSERT( ppx->unique() ); // no weak_ptrs should exist either, but there's no way to check that
detail::esft2_deleter_wrapper * pd = boost::get_deleter<detail::esft2_deleter_wrapper>( shared_this_ );
BOOST_ASSERT( pd != 0 );
pd->set_deleter( *ppx );
ppx->reset( shared_this_, ppx->get() );
shared_this_.reset();
}
}
};
} // namespace boost
#endif // #ifndef BOOST_ENABLE_SHARED_FROM_THIS2_HPP_INCLUDED

View File

@@ -0,0 +1,299 @@
#ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
#define BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
//
// intrusive_ptr.hpp
//
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation.
//
#include <boost/config.hpp>
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
# pragma warning(push)
# pragma warning(disable:4284) // odd return type for operator->
#endif
#include <boost/assert.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/smart_ptr/detail/sp_convertible.hpp>
#include <boost/config/no_tr1/functional.hpp> // for std::less
#if !defined(BOOST_NO_IOSTREAM)
#if !defined(BOOST_NO_IOSFWD)
#include <iosfwd> // for std::basic_ostream
#else
#include <ostream>
#endif
#endif
namespace boost
{
//
// intrusive_ptr
//
// A smart pointer that uses intrusive reference counting.
//
// Relies on unqualified calls to
//
// void intrusive_ptr_add_ref(T * p);
// void intrusive_ptr_release(T * p);
//
// (p != 0)
//
// The object is responsible for destroying itself.
//
template<class T> class intrusive_ptr
{
private:
typedef intrusive_ptr this_type;
public:
typedef T element_type;
intrusive_ptr(): px( 0 )
{
}
intrusive_ptr( T * p, bool add_ref = true ): px( p )
{
if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
}
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
template<class U>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
intrusive_ptr( intrusive_ptr<U> const & rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty() )
#else
intrusive_ptr( intrusive_ptr<U> const & rhs )
#endif
: px( rhs.get() )
{
if( px != 0 ) intrusive_ptr_add_ref( px );
}
#endif
intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
{
if( px != 0 ) intrusive_ptr_add_ref( px );
}
~intrusive_ptr()
{
if( px != 0 ) intrusive_ptr_release( px );
}
#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
{
this_type(rhs).swap(*this);
return *this;
}
#endif
// Move support
#if defined( BOOST_HAS_RVALUE_REFS )
intrusive_ptr(intrusive_ptr && rhs): px( rhs.px )
{
rhs.px = 0;
}
intrusive_ptr & operator=(intrusive_ptr && rhs)
{
this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
return *this;
}
#endif
intrusive_ptr & operator=(intrusive_ptr const & rhs)
{
this_type(rhs).swap(*this);
return *this;
}
intrusive_ptr & operator=(T * rhs)
{
this_type(rhs).swap(*this);
return *this;
}
void reset()
{
this_type().swap( *this );
}
void reset( T * rhs )
{
this_type( rhs ).swap( *this );
}
T * get() const
{
return px;
}
T & operator*() const
{
BOOST_ASSERT( px != 0 );
return *px;
}
T * operator->() const
{
BOOST_ASSERT( px != 0 );
return px;
}
// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
void swap(intrusive_ptr & rhs)
{
T * tmp = px;
px = rhs.px;
rhs.px = tmp;
}
private:
T * px;
};
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
{
return a.get() == b.get();
}
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
{
return a.get() != b.get();
}
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b)
{
return a.get() == b;
}
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b)
{
return a.get() != b;
}
template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b)
{
return a == b.get();
}
template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b)
{
return a != b.get();
}
#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
// Resolve the ambiguity between our op!= and the one in rel_ops
template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
{
return a.get() != b.get();
}
#endif
template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
{
return std::less<T *>()(a.get(), b.get());
}
template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
{
lhs.swap(rhs);
}
// mem_fn support
template<class T> T * get_pointer(intrusive_ptr<T> const & p)
{
return p.get();
}
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
{
return static_cast<T *>(p.get());
}
template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
{
return const_cast<T *>(p.get());
}
template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
{
return dynamic_cast<T *>(p.get());
}
// operator<<
#if !defined(BOOST_NO_IOSTREAM)
#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p)
{
os << p.get();
return os;
}
#else
// in STLport's no-iostreams mode no iostream symbols can be used
#ifndef _STLP_NO_IOSTREAMS
# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
using std::basic_ostream;
template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
# else
template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
# endif
{
os << p.get();
return os;
}
#endif // _STLP_NO_IOSTREAMS
#endif // __GNUC__ < 3
#endif // !defined(BOOST_NO_IOSTREAM)
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED

View File

@@ -0,0 +1,506 @@
#ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED
#define BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED
// make_shared.hpp
//
// Copyright (c) 2007, 2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://www.boost.org/libs/smart_ptr/make_shared.html
// for documentation.
#include <boost/config.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <cstddef>
#include <new>
namespace boost
{
namespace detail
{
template< std::size_t N, std::size_t A > struct sp_aligned_storage
{
union type
{
char data_[ N ];
typename boost::type_with_alignment< A >::type align_;
};
};
template< class T > class sp_ms_deleter
{
private:
typedef typename sp_aligned_storage< sizeof( T ), ::boost::alignment_of< T >::value >::type storage_type;
bool initialized_;
storage_type storage_;
private:
void destroy()
{
if( initialized_ )
{
reinterpret_cast< T* >( storage_.data_ )->~T();
initialized_ = false;
}
}
public:
sp_ms_deleter(): initialized_( false )
{
}
// optimization: do not copy storage_
sp_ms_deleter( sp_ms_deleter const & ): initialized_( false )
{
}
~sp_ms_deleter()
{
destroy();
}
void operator()( T * )
{
destroy();
}
void * address()
{
return storage_.data_;
}
void set_initialized()
{
initialized_ = true;
}
};
#if defined( BOOST_HAS_RVALUE_REFS )
template< class T > T&& forward( T &&t )
{
return t;
}
#endif
} // namespace detail
// Zero-argument versions
//
// Used even when variadic templates are available because of the new T() vs new T issue
template< class T > boost::shared_ptr< T > make_shared()
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T();
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A > boost::shared_ptr< T > allocate_shared( A const & a )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T();
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS )
// Variadic templates, rvalue reference
template< class T, class... Args > boost::shared_ptr< T > make_shared( Args && ... args )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( detail::forward<Args>( args )... );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class... Args > boost::shared_ptr< T > allocate_shared( A const & a, Args && ... args )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( detail::forward<Args>( args )... );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
#else
// C++03 version
template< class T, class A1 >
boost::shared_ptr< T > make_shared( A1 const & a1 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1 >
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2 >
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2 >
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3 >
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3 >
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4 >
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4 >
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4, class A5 >
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4, a5 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4, class A5 >
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4, a5 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4, class A5, class A6 >
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4, a5, a6 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6 >
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4, a5, a6 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7 >
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8 >
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
boost::shared_ptr< T > make_shared( A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >() );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
template< class T, class A, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9 >
boost::shared_ptr< T > allocate_shared( A const & a, A1 const & a1, A2 const & a2, A3 const & a3, A4 const & a4, A5 const & a5, A6 const & a6, A7 const & a7, A8 const & a8, A9 const & a9 )
{
boost::shared_ptr< T > pt( static_cast< T* >( 0 ), detail::sp_ms_deleter< T >(), a );
detail::sp_ms_deleter< T > * pd = boost::get_deleter< detail::sp_ms_deleter< T > >( pt );
void * pv = pd->address();
::new( pv ) T( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
pd->set_initialized();
T * pt2 = static_cast< T* >( pv );
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
return boost::shared_ptr< T >( pt, pt2 );
}
#endif
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_HPP_INCLUDED

View File

@@ -0,0 +1,107 @@
#ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED
#define BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// http://www.boost.org/libs/smart_ptr/scoped_array.htm
//
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/config.hpp> // in case ptrdiff_t not in std
#include <boost/detail/workaround.hpp>
#include <cstddef> // for std::ptrdiff_t
namespace boost
{
// Debug hooks
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
void sp_array_constructor_hook(void * p);
void sp_array_destructor_hook(void * p);
#endif
// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
// is guaranteed, either on destruction of the scoped_array or via an explicit
// reset(). Use shared_array or std::vector if your needs are more complex.
template<class T> class scoped_array // noncopyable
{
private:
T * px;
scoped_array(scoped_array const &);
scoped_array & operator=(scoped_array const &);
typedef scoped_array<T> this_type;
void operator==( scoped_array const& ) const;
void operator!=( scoped_array const& ) const;
public:
typedef T element_type;
explicit scoped_array( T * p = 0 ) : px( p ) // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_array_constructor_hook( px );
#endif
}
~scoped_array() // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_array_destructor_hook( px );
#endif
boost::checked_array_delete( px );
}
void reset(T * p = 0) // never throws
{
BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
this_type(p).swap(*this);
}
T & operator[](std::ptrdiff_t i) const // never throws
{
BOOST_ASSERT( px != 0 );
BOOST_ASSERT( i >= 0 );
return px[i];
}
T * get() const // never throws
{
return px;
}
// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
void swap(scoped_array & b) // never throws
{
T * tmp = b.px;
b.px = px;
px = tmp;
}
};
template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) // never throws
{
a.swap(b);
}
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_SCOPED_ARRAY_HPP_INCLUDED

View File

@@ -0,0 +1,131 @@
#ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
#define BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm
//
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/detail/workaround.hpp>
#ifndef BOOST_NO_AUTO_PTR
# include <memory> // for std::auto_ptr
#endif
namespace boost
{
// Debug hooks
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
void sp_scalar_constructor_hook(void * p);
void sp_scalar_destructor_hook(void * p);
#endif
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
// of the object pointed to, either on destruction of the scoped_ptr or via
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
// use shared_ptr or std::auto_ptr if your needs are more complex.
template<class T> class scoped_ptr // noncopyable
{
private:
T * px;
scoped_ptr(scoped_ptr const &);
scoped_ptr & operator=(scoped_ptr const &);
typedef scoped_ptr<T> this_type;
void operator==( scoped_ptr const& ) const;
void operator!=( scoped_ptr const& ) const;
public:
typedef T element_type;
explicit scoped_ptr( T * p = 0 ): px( p ) // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_constructor_hook( px );
#endif
}
#ifndef BOOST_NO_AUTO_PTR
explicit scoped_ptr( std::auto_ptr<T> p ): px( p.release() ) // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_constructor_hook( px );
#endif
}
#endif
~scoped_ptr() // never throws
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_destructor_hook( px );
#endif
boost::checked_delete( px );
}
void reset(T * p = 0) // never throws
{
BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
this_type(p).swap(*this);
}
T & operator*() const // never throws
{
BOOST_ASSERT( px != 0 );
return *px;
}
T * operator->() const // never throws
{
BOOST_ASSERT( px != 0 );
return px;
}
T * get() const // never throws
{
return px;
}
// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
void swap(scoped_ptr & b) // never throws
{
T * tmp = b.px;
b.px = px;
px = tmp;
}
};
template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws
{
a.swap(b);
}
// get_pointer(p) is a generic way to say p.get()
template<class T> inline T * get_pointer(scoped_ptr<T> const & p)
{
return p.get();
}
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_SCOPED_PTR_HPP_INCLUDED

View File

@@ -0,0 +1,147 @@
#ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED
#define BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED
//
// shared_array.hpp
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001, 2002 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation.
//
#include <boost/config.hpp> // for broken compiler workarounds
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#include <boost/smart_ptr/detail/shared_array_nmt.hpp>
#else
#include <memory> // TR1 cyclic inclusion fix
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/smart_ptr/detail/shared_count.hpp>
#include <boost/detail/workaround.hpp>
#include <cstddef> // for std::ptrdiff_t
#include <algorithm> // for std::swap
#include <functional> // for std::less
namespace boost
{
//
// shared_array
//
// shared_array extends shared_ptr to arrays.
// The array pointed to is deleted when the last shared_array pointing to it
// is destroyed or reset.
//
template<class T> class shared_array
{
private:
// Borland 5.5.1 specific workarounds
typedef checked_array_deleter<T> deleter;
typedef shared_array<T> this_type;
public:
typedef T element_type;
explicit shared_array(T * p = 0): px(p), pn(p, deleter())
{
}
//
// Requirements: D's copy constructor must not throw
//
// shared_array will release p by calling d(p)
//
template<class D> shared_array(T * p, D d): px(p), pn(p, d)
{
}
// generated copy constructor, assignment, destructor are fine
void reset(T * p = 0)
{
BOOST_ASSERT(p == 0 || p != px);
this_type(p).swap(*this);
}
template <class D> void reset(T * p, D d)
{
this_type(p, d).swap(*this);
}
T & operator[] (std::ptrdiff_t i) const // never throws
{
BOOST_ASSERT(px != 0);
BOOST_ASSERT(i >= 0);
return px[i];
}
T * get() const // never throws
{
return px;
}
// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
bool unique() const // never throws
{
return pn.unique();
}
long use_count() const // never throws
{
return pn.use_count();
}
void swap(shared_array<T> & other) // never throws
{
std::swap(px, other.px);
pn.swap(other.pn);
}
private:
T * px; // contained pointer
detail::shared_count pn; // reference counter
}; // shared_array
template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) // never throws
{
return a.get() == b.get();
}
template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) // never throws
{
return a.get() != b.get();
}
template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) // never throws
{
return std::less<T*>()(a.get(), b.get());
}
template<class T> void swap(shared_array<T> & a, shared_array<T> & b) // never throws
{
a.swap(b);
}
} // namespace boost
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#endif // #ifndef BOOST_SMART_PTR_SHARED_ARRAY_HPP_INCLUDED

View File

@@ -0,0 +1,701 @@
#ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
#define BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
//
// shared_ptr.hpp
//
// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
// Copyright (c) 2001-2008 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
//
#include <boost/config.hpp> // for broken compiler workarounds
#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#include <boost/smart_ptr/detail/shared_ptr_nmt.hpp>
#else
// In order to avoid circular dependencies with Boost.TR1
// we make sure that our include of <memory> doesn't try to
// pull in the TR1 headers: that's why we use this header
// rather than including <memory> directly:
#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/detail/shared_count.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/smart_ptr/detail/sp_convertible.hpp>
#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
#include <boost/smart_ptr/detail/spinlock_pool.hpp>
#include <boost/memory_order.hpp>
#endif
#include <algorithm> // for std::swap
#include <functional> // for std::less
#include <typeinfo> // for std::bad_cast
#if !defined(BOOST_NO_IOSTREAM)
#if !defined(BOOST_NO_IOSFWD)
#include <iosfwd> // for std::basic_ostream
#else
#include <ostream>
#endif
#endif
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
# pragma warning(push)
# pragma warning(disable:4284) // odd return type for operator->
#endif
namespace boost
{
template<class T> class shared_ptr;
template<class T> class weak_ptr;
template<class T> class enable_shared_from_this;
template<class T> class enable_shared_from_this2;
namespace detail
{
struct static_cast_tag {};
struct const_cast_tag {};
struct dynamic_cast_tag {};
struct polymorphic_cast_tag {};
template<class T> struct shared_ptr_traits
{
typedef T & reference;
};
template<> struct shared_ptr_traits<void>
{
typedef void reference;
};
#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
template<> struct shared_ptr_traits<void const>
{
typedef void reference;
};
template<> struct shared_ptr_traits<void volatile>
{
typedef void reference;
};
template<> struct shared_ptr_traits<void const volatile>
{
typedef void reference;
};
#endif
// enable_shared_from_this support
template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe )
{
if( pe != 0 )
{
pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
}
}
template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_this2< T > const * pe )
{
if( pe != 0 )
{
pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
}
}
#ifdef _MANAGED
// Avoid C4793, ... causes native code generation
struct sp_any_pointer
{
template<class T> sp_any_pointer( T* ) {}
};
inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
{
}
#else // _MANAGED
inline void sp_enable_shared_from_this( ... )
{
}
#endif // _MANAGED
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
// rvalue auto_ptr support based on a technique by Dave Abrahams
template< class T, class R > struct sp_enable_if_auto_ptr
{
};
template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
{
typedef R type;
};
#endif
} // namespace detail
//
// shared_ptr
//
// An enhanced relative of scoped_ptr with reference counted copy semantics.
// The object pointed to is deleted when the last shared_ptr pointing to it
// is destroyed or reset.
//
template<class T> class shared_ptr
{
private:
// Borland 5.5.1 specific workaround
typedef shared_ptr<T> this_type;
public:
typedef T element_type;
typedef T value_type;
typedef T * pointer;
typedef typename boost::detail::shared_ptr_traits<T>::reference reference;
shared_ptr(): px(0), pn() // never throws in 1.30+
{
}
template<class Y>
explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
{
boost::detail::sp_enable_shared_from_this( this, p, p );
}
//
// Requirements: D's copy constructor must not throw
//
// shared_ptr will release p by calling d(p)
//
template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
{
boost::detail::sp_enable_shared_from_this( this, p, p );
}
// As above, but with allocator. A's copy constructor shall not throw.
template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
{
boost::detail::sp_enable_shared_from_this( this, p, p );
}
// generated copy constructor, destructor are fine
template<class Y>
explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
{
// it is now safe to copy r.px, as pn(r.pn) did not throw
px = r.px;
}
template<class Y>
shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag ): px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) // never throws
{
if( !pn.empty() )
{
px = r.px;
}
}
template<class Y>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
#else
shared_ptr( shared_ptr<Y> const & r )
#endif
: px( r.px ), pn( r.pn ) // never throws
{
}
// aliasing
template< class Y >
shared_ptr( shared_ptr<Y> const & r, T * p ): px( p ), pn( r.pn ) // never throws
{
}
template<class Y>
shared_ptr(shared_ptr<Y> const & r, boost::detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
{
}
template<class Y>
shared_ptr(shared_ptr<Y> const & r, boost::detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
{
}
template<class Y>
shared_ptr(shared_ptr<Y> const & r, boost::detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
{
if(px == 0) // need to allocate new counter -- the cast failed
{
pn = boost::detail::shared_count();
}
}
template<class Y>
shared_ptr(shared_ptr<Y> const & r, boost::detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
{
if(px == 0)
{
boost::throw_exception(std::bad_cast());
}
}
#ifndef BOOST_NO_AUTO_PTR
template<class Y>
explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
{
Y * tmp = r.get();
pn = boost::detail::shared_count(r);
boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
}
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
template<class Ap>
explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
{
typename Ap::element_type * tmp = r.get();
pn = boost::detail::shared_count( r );
boost::detail::sp_enable_shared_from_this( this, tmp, tmp );
}
#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#endif // BOOST_NO_AUTO_PTR
// assignment
shared_ptr & operator=( shared_ptr const & r ) // never throws
{
this_type(r).swap(*this);
return *this;
}
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
template<class Y>
shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
{
this_type(r).swap(*this);
return *this;
}
#endif
#ifndef BOOST_NO_AUTO_PTR
template<class Y>
shared_ptr & operator=( std::auto_ptr<Y> & r )
{
this_type(r).swap(*this);
return *this;
}
#if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
template<class Ap>
typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
{
this_type( r ).swap( *this );
return *this;
}
#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#endif // BOOST_NO_AUTO_PTR
// Move support
#if defined( BOOST_HAS_RVALUE_REFS )
shared_ptr( shared_ptr && r ): px( r.px ), pn() // never throws
{
pn.swap( r.pn );
r.px = 0;
}
template<class Y>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
#else
shared_ptr( shared_ptr<Y> && r )
#endif
: px( r.px ), pn() // never throws
{
pn.swap( r.pn );
r.px = 0;
}
shared_ptr & operator=( shared_ptr && r ) // never throws
{
this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
return *this;
}
template<class Y>
shared_ptr & operator=( shared_ptr<Y> && r ) // never throws
{
this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
return *this;
}
#endif
void reset() // never throws in 1.30+
{
this_type().swap(*this);
}
template<class Y> void reset(Y * p) // Y must be complete
{
BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
this_type(p).swap(*this);
}
template<class Y, class D> void reset( Y * p, D d )
{
this_type( p, d ).swap( *this );
}
template<class Y, class D, class A> void reset( Y * p, D d, A a )
{
this_type( p, d, a ).swap( *this );
}
template<class Y> void reset( shared_ptr<Y> const & r, T * p )
{
this_type( r, p ).swap( *this );
}
reference operator* () const // never throws
{
BOOST_ASSERT(px != 0);
return *px;
}
T * operator-> () const // never throws
{
BOOST_ASSERT(px != 0);
return px;
}
T * get() const // never throws
{
return px;
}
// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
bool unique() const // never throws
{
return pn.unique();
}
long use_count() const // never throws
{
return pn.use_count();
}
void swap(shared_ptr<T> & other) // never throws
{
std::swap(px, other.px);
pn.swap(other.pn);
}
template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
{
return pn < rhs.pn;
}
void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const
{
return pn.get_deleter( ti );
}
bool _internal_equiv( shared_ptr const & r ) const
{
return px == r.px && pn == r.pn;
}
// Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston)
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private:
template<class Y> friend class shared_ptr;
template<class Y> friend class weak_ptr;
#endif
T * px; // contained pointer
boost::detail::shared_count pn; // reference counter
}; // shared_ptr
template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
{
return a.get() == b.get();
}
template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
{
return a.get() != b.get();
}
#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
// Resolve the ambiguity between our op!= and the one in rel_ops
template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
{
return a.get() != b.get();
}
#endif
template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
{
return a._internal_less(b);
}
template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
{
a.swap(b);
}
template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
{
return shared_ptr<T>(r, boost::detail::static_cast_tag());
}
template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r)
{
return shared_ptr<T>(r, boost::detail::const_cast_tag());
}
template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
{
return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
}
// shared_*_cast names are deprecated. Use *_pointer_cast instead.
template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
{
return shared_ptr<T>(r, boost::detail::static_cast_tag());
}
template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
{
return shared_ptr<T>(r, boost::detail::dynamic_cast_tag());
}
template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
{
return shared_ptr<T>(r, boost::detail::polymorphic_cast_tag());
}
template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
{
BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
return shared_static_cast<T>(r);
}
// get_pointer() enables boost::mem_fn to recognize shared_ptr
template<class T> inline T * get_pointer(shared_ptr<T> const & p)
{
return p.get();
}
// operator<<
#if !defined(BOOST_NO_IOSTREAM)
#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
{
os << p.get();
return os;
}
#else
// in STLport's no-iostreams mode no iostream symbols can be used
#ifndef _STLP_NO_IOSTREAMS
# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
using std::basic_ostream;
template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
# else
template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
# endif
{
os << p.get();
return os;
}
#endif // _STLP_NO_IOSTREAMS
#endif // __GNUC__ < 3
#endif // !defined(BOOST_NO_IOSTREAM)
// get_deleter
#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
// g++ 2.9x doesn't allow static_cast<X const *>(void *)
// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
{
void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
return const_cast<D *>(static_cast<D const *>(q));
}
#else
template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
{
return static_cast<D *>(p._internal_get_deleter(BOOST_SP_TYPEID(D)));
}
#endif
// atomic access
#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ )
{
return false;
}
template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
{
boost::detail::spinlock_pool<2>::scoped_lock lock( p );
return *p;
}
template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, memory_order /*mo*/ )
{
return atomic_load( p );
}
template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
{
boost::detail::spinlock_pool<2>::scoped_lock lock( p );
p->swap( r );
}
template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
{
atomic_store( p, r ); // std::move( r )
}
template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
{
boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
sp.lock();
p->swap( r );
sp.unlock();
return r; // return std::move( r )
}
template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, memory_order /*mo*/ )
{
return atomic_exchange( p, r ); // std::move( r )
}
template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
{
boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
sp.lock();
if( p->_internal_equiv( *v ) )
{
p->swap( w );
sp.unlock();
return true;
}
else
{
shared_ptr<T> tmp( *p );
sp.unlock();
tmp.swap( *v );
return false;
}
}
template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, memory_order /*success*/, memory_order /*failure*/ )
{
return atomic_compare_exchange( p, v, w ); // std::move( w )
}
#endif
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
#endif // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED

View File

@@ -0,0 +1,230 @@
#ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
#define BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED
//
// weak_ptr.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation.
//
#include <memory> // boost.TR1 include order fix
#include <boost/smart_ptr/detail/shared_count.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#ifdef BOOST_MSVC // moved here to work around VC++ compiler crash
# pragma warning(push)
# pragma warning(disable:4284) // odd return type for operator->
#endif
namespace boost
{
template<class T> class weak_ptr
{
private:
// Borland 5.5.1 specific workarounds
typedef weak_ptr<T> this_type;
public:
typedef T element_type;
weak_ptr(): px(0), pn() // never throws in 1.30+
{
}
// generated copy constructor, assignment, destructor are fine
//
// The "obvious" converting constructor implementation:
//
// template<class Y>
// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
// {
// }
//
// has a serious problem.
//
// r.px may already have been invalidated. The px(r.px)
// conversion may require access to *r.px (virtual inheritance).
//
// It is not possible to avoid spurious access violations since
// in multithreaded programs r.px may be invalidated at any point.
//
template<class Y>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
weak_ptr( weak_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
#else
weak_ptr( weak_ptr<Y> const & r )
#endif
: px(r.lock().get()), pn(r.pn) // never throws
{
}
#if defined( BOOST_HAS_RVALUE_REFS )
template<class Y>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
weak_ptr( weak_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
#else
weak_ptr( weak_ptr<Y> && r )
#endif
: px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) // never throws
{
r.px = 0;
}
// for better efficiency in the T == Y case
weak_ptr( weak_ptr && r ): px( r.px ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) // never throws
{
r.px = 0;
}
// for better efficiency in the T == Y case
weak_ptr & operator=( weak_ptr && r ) // never throws
{
this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
return *this;
}
#endif
template<class Y>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
weak_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
#else
weak_ptr( shared_ptr<Y> const & r )
#endif
: px( r.px ), pn( r.pn ) // never throws
{
}
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
template<class Y>
weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
{
px = r.lock().get();
pn = r.pn;
return *this;
}
#if defined( BOOST_HAS_RVALUE_REFS )
template<class Y>
weak_ptr & operator=( weak_ptr<Y> && r )
{
this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this );
return *this;
}
#endif
template<class Y>
weak_ptr & operator=(shared_ptr<Y> const & r) // never throws
{
px = r.px;
pn = r.pn;
return *this;
}
#endif
shared_ptr<T> lock() const // never throws
{
return shared_ptr<element_type>( *this, boost::detail::sp_nothrow_tag() );
}
long use_count() const // never throws
{
return pn.use_count();
}
bool expired() const // never throws
{
return pn.use_count() == 0;
}
bool _empty() const // extension, not in std::weak_ptr
{
return pn.empty();
}
void reset() // never throws in 1.30+
{
this_type().swap(*this);
}
void swap(this_type & other) // never throws
{
std::swap(px, other.px);
pn.swap(other.pn);
}
void _internal_assign(T * px2, boost::detail::shared_count const & pn2)
{
px = px2;
pn = pn2;
}
template<class Y> bool _internal_less(weak_ptr<Y> const & rhs) const
{
return pn < rhs.pn;
}
// Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston)
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private:
template<class Y> friend class weak_ptr;
template<class Y> friend class shared_ptr;
#endif
T * px; // contained pointer
boost::detail::weak_count pn; // reference counter
}; // weak_ptr
template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b)
{
return a._internal_less(b);
}
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
{
a.swap(b);
}
} // namespace boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED

View File

@@ -0,0 +1,18 @@
#ifndef BOOST_WEAK_PTR_HPP_INCLUDED
#define BOOST_WEAK_PTR_HPP_INCLUDED
//
// weak_ptr.hpp
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation.
//
#include <boost/smart_ptr/weak_ptr.hpp>
#endif // #ifndef BOOST_WEAK_PTR_HPP_INCLUDED

15
index.html Normal file
View File

@@ -0,0 +1,15 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=smart_ptr.htm">
</head>
<body>
Automatic redirection failed, please go to
<a href="smart_ptr.htm">smart_ptr.htm</a>.
</body>
</html>
<!--
<09> Copyright Beman Dawes, 2001
Distributed under the Boost Software License, Version 1.0.
See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt
-->

297
intrusive_ptr.html Normal file
View File

@@ -0,0 +1,297 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>intrusive_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body text="#000000" bgColor="#ffffff">
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
border="0"></A>intrusive_ptr class template</h1>
<p>
<A href="#Introduction">Introduction</A><br>
<A href="#Synopsis">Synopsis</A><br>
<A href="#Members">Members</A><br>
<A href="#functions">Free Functions</A><br>
</p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <b>intrusive_ptr</b> class template stores a pointer to an object with an
embedded reference count. Every new <b>intrusive_ptr</b> instance increments
the reference count by using an unqualified call to the function <STRONG>intrusive_ptr_add_ref</STRONG>,
passing it the pointer as an argument. Similarly, when an <STRONG>intrusive_ptr</STRONG>
is destroyed, it calls <STRONG>intrusive_ptr_release</STRONG>; this function is
responsible for destroying the object when its reference count drops to zero.
The user is expected to provide suitable definitions of these two functions. On
compilers that support argument-dependent lookup, <STRONG>intrusive_ptr_add_ref</STRONG>
and <STRONG>intrusive_ptr_release</STRONG> should be defined in the namespace
that corresponds to their parameter; otherwise, the definitions need to go in
namespace <STRONG>boost</STRONG>.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <STRONG>intrusive_ptr&lt;T&gt;</STRONG> can be implicitly converted to <STRONG>intrusive_ptr&lt;U&gt;</STRONG>
whenever <STRONG>T*</STRONG> can be implicitly converted to <STRONG>U*</STRONG>.</p>
<P>The main reasons to use <STRONG>intrusive_ptr</STRONG> are:</P>
<UL>
<LI>
Some existing frameworks or OSes provide objects with embedded reference
counts;
<LI>
The memory footprint of <STRONG>intrusive_ptr</STRONG>
is the same as the corresponding raw pointer;
<LI>
<STRONG>intrusive_ptr&lt;T&gt;</STRONG> can be constructed from an arbitrary
raw pointer of type <STRONG>T *</STRONG>.</LI></UL>
<P>As a general rule, if it isn't obvious whether <STRONG>intrusive_ptr</STRONG> better
fits your needs than <STRONG>shared_ptr</STRONG>, try a <STRONG>shared_ptr</STRONG>-based
design first.</P>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;class T&gt; class intrusive_ptr {
public:
typedef T <A href="#element_type" >element_type</A>;
<A href="#constructors" >intrusive_ptr</A>(); // never throws
<A href="#constructors" >intrusive_ptr</A>(T * p, bool add_ref = true);
<A href="#constructors" >intrusive_ptr</A>(intrusive_ptr const &amp; r);
template&lt;class Y&gt; <A href="#constructors" >intrusive_ptr</A>(intrusive_ptr&lt;Y&gt; const &amp; r);
<A href="#destructor" >~intrusive_ptr</A>();
intrusive_ptr &amp; <A href="#assignment" >operator=</A>(intrusive_ptr const &amp; r);
template&lt;class Y&gt; intrusive_ptr &amp; <A href="#assignment" >operator=</A>(intrusive_ptr&lt;Y&gt; const &amp; r);
intrusive_ptr &amp; <A href="#assignment" >operator=</A>(T * r);
void <a href="#reset" >reset</a>();
void <a href="#reset" >reset</a>(T * r);
T &amp; <A href="#indirection" >operator*</A>() const; // never throws
T * <A href="#indirection" >operator-&gt;</A>() const; // never throws
T * <A href="#get" >get</A>() const; // never throws
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
void <A href="#swap" >swap</A>(intrusive_ptr &amp; b); // never throws
};
template&lt;class T, class U&gt;
bool <A href="#comparison" >operator==</A>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T, class U&gt;
bool <A href="#comparison" >operator!=</A>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T&gt;
bool <A href="#comparison" >operator==</A>(intrusive_ptr&lt;T&gt; const &amp; a, T * b); // never throws
template&lt;class T&gt;
bool <A href="#comparison" >operator!=</A>(intrusive_ptr&lt;T&gt; const &amp; a, T * b); // never throws
template&lt;class T&gt;
bool <A href="#comparison" >operator==</A>(T * a, intrusive_ptr&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt;
bool <A href="#comparison" >operator!=</A>(T * a, intrusive_ptr&lt;T&gt; const &amp; b); // never throws
template&lt;class T, class U&gt;
bool <A href="#comparison" >operator&lt;</A>(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T&gt; void <A href="#free-swap" >swap</A>(intrusive_ptr&lt;T&gt; &amp; a, intrusive_ptr&lt;T&gt; &amp; b); // never throws
template&lt;class T&gt; T * <A href="#get_pointer" >get_pointer</A>(intrusive_ptr&lt;T&gt; const &amp; p); // never throws
template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; <A href="#static_pointer_cast" >static_pointer_cast</A>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; <A href="#const_pointer_cast" >const_pointer_cast</A>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; <A href="#dynamic_pointer_cast" >dynamic_pointer_cast</A>(intrusive_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class E, class T, class Y&gt;
std::basic_ostream&lt;E, T&gt; &amp; <A href="#insertion-operator" >operator&lt;&lt;</A> (std::basic_ostream&lt;E, T&gt; &amp; os, intrusive_ptr&lt;Y&gt; const &amp; p);
}</pre>
<h2><a name="Members">Members</a></h2>
<h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre>
<blockquote>
<p>Provides the type of the template parameter T.</p>
</blockquote>
<h3><a name="constructors">constructors</a></h3>
<pre>intrusive_ptr(); // never throws</pre>
<blockquote>
<p><b>Postconditions:</b> <code>get() == 0</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>intrusive_ptr(T * p, bool add_ref = true);</pre>
<blockquote>
<p><b>Effects:</b> <code>if(p != 0 &amp;&amp; add_ref) intrusive_ptr_add_ref(p);</code>.</p>
<p><b>Postconditions:</b> <code>get() == p</code>.</p>
</blockquote>
<pre>intrusive_ptr(intrusive_ptr const &amp; r);
template&lt;class Y&gt; intrusive_ptr(intrusive_ptr&lt;Y&gt; const &amp; r);</pre>
<blockquote>
<p><b>Effects:</b> <code>if(r.get() != 0) intrusive_ptr_add_ref(r.get());</code>.</p>
<p><b>Postconditions:</b> <code>get() == r.get()</code>.</p>
</blockquote>
<h3><a name="destructor">destructor</a></h3>
<pre>~intrusive_ptr();</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> <code>if(get() != 0) intrusive_ptr_release(get());</code>.</P>
</BLOCKQUOTE>
<H3><a name="assignment">assignment</a></H3>
<pre>intrusive_ptr &amp; operator=(intrusive_ptr const &amp; r);
template&lt;class Y&gt; intrusive_ptr &amp; operator=(intrusive_ptr&lt;Y&gt; const &amp; r);
intrusive_ptr &amp; operator=(T * r);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</P>
<P><B>Returns:</B> <code>*this</code>.</P>
</BLOCKQUOTE>
<H3><a name="reset">reset</a></H3>
<pre>void reset();</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr().swap(*this)</code>.</P>
</BLOCKQUOTE>
<pre>void reset(T * r);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>intrusive_ptr(r).swap(*this)</code>.</P>
</BLOCKQUOTE>
<h3><a name="indirection">indirection</a></h3>
<pre>T &amp; operator*() const; // never throws</pre>
<blockquote>
<p><b>Requirements:</b> <code>get() != 0</code>.</p>
<p><b>Returns:</b> <code>*get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>T * operator-&gt;() const; // never throws</pre>
<blockquote>
<p><b>Requirements:</b> <code>get() != 0</code>.</p>
<p><b>Returns:</b> <code>get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> the stored pointer.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h3><a name="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> an unspecified value that, when used in boolean contexts, is
equivalent to <code>get() != 0</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> This conversion operator allows <b>intrusive_ptr</b> objects to be
used in boolean contexts, like <code>if (p &amp;&amp; p-&gt;valid()) {}</code>.
The actual target type is typically a pointer to a member function, avoiding
many of the implicit conversion pitfalls.</P>
</blockquote>
<h3><a name="swap">swap</a></h3>
<pre>void swap(intrusive_ptr &amp; b); // never throws</pre>
<blockquote>
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3>
<pre>template&lt;class T, class U&gt;
bool operator==(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T, class U&gt;
bool operator!=(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T, class U&gt;
bool operator==(intrusive_ptr&lt;T&gt; const &amp; a, U * b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() == b</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T, class U&gt;
bool operator!=(intrusive_ptr&lt;T&gt; const &amp; a, U * b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() != b</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T, class U&gt;
bool operator==(T * a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a == b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T, class U&gt;
bool operator!=(T * a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a != b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T, class U&gt;
bool operator&lt;(intrusive_ptr&lt;T&gt; const &amp; a, intrusive_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>std::less&lt;T *&gt;()(a.get(), b.get())</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Allows <STRONG>intrusive_ptr</STRONG> objects to be used as keys
in associative containers.</P>
</blockquote>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt;
void swap(intrusive_ptr&lt;T&gt; &amp; a, intrusive_ptr&lt;T&gt; &amp; b); // never throws</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
generic programming.</P>
</BLOCKQUOTE>
<h3><a name="get_pointer">get_pointer</a></h3>
<pre>template&lt;class T&gt;
T * get_pointer(intrusive_ptr&lt;T&gt; const &amp; p); // never throws</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>p.get()</code>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> Provided as an aid to generic programming. Used by <A href="../bind/mem_fn.html">
mem_fn</A>.</P>
</BLOCKQUOTE>
<h3><a name="static_pointer_cast">static_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; static_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>intrusive_ptr&lt;T&gt;(static_cast&lt;T*&gt;(r.get()))</code>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h3><a name="const_pointer_cast">const_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; const_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>intrusive_ptr&lt;T&gt;(const_cast&lt;T*&gt;(r.get()))</code>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h3><a name="dynamic_pointer_cast">dynamic_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt;
intrusive_ptr&lt;T&gt; dynamic_pointer_cast(intrusive_ptr&lt;U&gt; const &amp; r);</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>intrusive_ptr&lt;T&gt;(dynamic_cast&lt;T*&gt;(r.get()))</code>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h3><a name="insertion-operator">operator&lt;&lt;</a></h3>
<pre>template&lt;class E, class T, class Y&gt;
std::basic_ostream&lt;E, T&gt; &amp; operator&lt;&lt; (std::basic_ostream&lt;E, T&gt; &amp; os, intrusive_ptr&lt;Y&gt; const &amp; p);</pre>
<BLOCKQUOTE>
<p><STRONG>Effects:</STRONG> <code>os &lt;&lt; p.get();</code>.</p>
<P><B>Returns:</B> <code>os</code>.</P>
</BLOCKQUOTE>
<hr>
<p>
$Date$</p>
<p>
<small>Copyright <20> 2003-2005 Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

119
make_shared.html Normal file
View File

@@ -0,0 +1,119 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>make_shared and allocate_shared</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body text="#000000" bgColor="#ffffff">
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
border="0"></A>make_shared and allocate_shared function templates</h1>
<p><A href="#Introduction">Introduction</A><br>
<A href="#Synopsis">Synopsis</A><br>
<A href="#functions">Free Functions</A><br>
<A href="#example">Example</A><br>
<h2><a name="Introduction">Introduction</a></h2>
<p>Consistent use of <a href="shared_ptr.htm"><code>shared_ptr</code></a>
can eliminate the need to use an explicit <code>delete</code>,
but alone it provides no support in avoiding explicit <code>new</code>.
There have been repeated requests from users for a factory function that creates
an object of a given type and returns a <code>shared_ptr</code> to it.
Besides convenience and style, such a function is also exception safe and
considerably faster because it can use a single allocation for both the object
and its corresponding control block, eliminating a significant portion of
<code>shared_ptr</code>'s construction overhead.
This eliminates one of the major efficiency complaints about <code>shared_ptr</code>.
</p>
<p>The header file &lt;boost/make_shared.hpp&gt; provides a family of overloaded function templates,
<code>make_shared</code> and <code>allocate_shared</code>, to address this need.
<code>make_shared</code> uses the global operator <code>new</code> to allocate memory,
whereas <code>allocate_shared</code> uses an user-supplied allocator, allowing finer control.</p>
<p>
The rationale for choosing the name <code>make_shared</code> is that the expression
<code>make_shared&lt;Widget&gt;()</code> can be read aloud and conveys the intended meaning.</p>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
template&lt;typename T&gt; class shared_ptr;
template&lt;typename T&gt;
shared_ptr&lt;T&gt; <a href="#functions">make_shared</a>();
template&lt;typename T, typename A&gt;
shared_ptr&lt;T&gt; <a href="#functions">allocate_shared</a>( A const &amp; );
#if defined( BOOST_HAS_VARIADIC_TMPL ) && defined( BOOST_HAS_RVALUE_REFS ) // C++0x prototypes
template&lt;typename T, typename... Args&gt;
shared_ptr&lt;T&gt; <a href="#functions">make_shared</a>( Args &amp;&amp; ... args );
template&lt;typename T, typename A, typename... Args&gt;
shared_ptr&lt;T&gt; <a href="#functions">allocate_shared</a>( A const &amp; a, Args &amp;&amp; ... args );
#else // no C++0X support
template&lt;typename T, typename Arg1 &gt;
shared_ptr&lt;T&gt; <a href="#functions">make_shared</a>( Arg1 const &amp; arg1 );
template&lt;typename T, typename Arg1, typename Arg2 &gt;
shared_ptr&lt;T&gt; <a href="#functions">make_shared</a>( Arg1 const &amp; arg1, Arg2 const &amp; arg2 );
// ...
template&lt;typename T, typename Arg1, typename Arg2, ..., typename ArgN &gt;
shared_ptr&lt;T&gt; <a href="#functions">make_shared</a>( Arg1 const &amp; arg1, Arg2 const &amp; arg2, ..., ArgN const &amp; argN );
template&lt;typename T, typename A, typename Arg1 &gt;
shared_ptr&lt;T&gt; <a href="#functions">allocate_shared</a>( A const &amp; a, Arg1 const &amp; arg1 );
template&lt;typename T, typename A, typename Arg1, typename Arg2 &gt;
shared_ptr&lt;T&gt; <a href="#functions">allocate_shared</a>( Arg1 const &amp; arg1, Arg2 const &amp; arg2 );
// ...
template&lt;typename T, typename A, typename Arg1, typename Arg2, ..., typename ArgN &gt;
shared_ptr&lt;T&gt; <a href="#functions">allocate_shared</a>( A const &amp; a, Arg1 const &amp; arg1, Arg2 const &amp; arg2, ..., ArgN const &amp; argN );
#endif
}</pre>
<h2><a name="functions">Free Functions</a></h2>
<pre>template&lt;class T, class... Args&gt;
shared_ptr&lt;T&gt; make_shared( Args &amp;&amp; ... args );
template&lt;class T, class A, class... Args&gt;
shared_ptr&lt;T&gt; allocate_shared( A const &amp; a, Args &amp;&amp; ... args );</pre>
<blockquote>
<p><b>Requires:</b> The expression <code>new( pv ) T( std::forward&lt;Args&gt;(args)... )</code>,
where <code>pv</code> is a <code>void*</code> pointing to storage suitable
to hold an object of type <code>T</code>,
shall be well-formed. <code>A</code> shall be an <em>Allocator</em>,
as described in section 20.1.5 (<stong>Allocator requirements</strong>) of the C++ Standard.
The copy constructor and destructor of <code>A</code> shall not throw.</p>
<p><b>Effects:</b> Allocates memory suitable for an object of type <code>T</code>
and constructs an object in it via the placement new expression <code>new( pv ) T()</code>
or <code>new( pv ) T( std::forward&lt;Args&gt;(args)... )</code>.
<code>allocate_shared</code> uses a copy of <code>a</code> to allocate memory.
If an exception is thrown, has no effect.</p>
<p><b>Returns:</b> A <code>shared_ptr</code> instance that stores and owns the address
of the newly constructed object of type <code>T</code>.</p>
<p><b>Postconditions:</b> <code>get() != 0 &amp;&amp; use_count() == 1</code>.</p>
<p><b>Throws:</b> <code>bad_alloc</code>, or an exception thrown from <code>A::allocate</code>
or the constructor of <code>T</code>.</p>
<p><b>Notes:</b> This implementation allocates the memory required for the
returned <code>shared_ptr</code> and an object of type <code>T</code> in a single
allocation. This provides efficiency equivalent to an intrusive smart pointer.</p>
<p>The prototypes shown above are used if your compiler supports rvalue references
and variadic templates. They perfectly forward the <code>args</code> parameters to
the constructors of <code>T</code>.</p>
<p>Otherwise, the implementation will fall back on
forwarding the arguments to the constructors of <code>T</code> as const references.
If you need to pass a non-const reference to a constructor of <code>T</code>,
you may do so by wrapping the parameter in a call to <code>boost::ref</code>.
In addition, you will be
limited to a maximum of 9 arguments (not counting the allocator argument of
allocate_shared).</p>
</blockquote>
<h2><a name="example">Example</a></h2>
<pre>boost::shared_ptr&lt;std::string&gt; x = boost::make_shared&lt;std::string&gt;("hello, world!");
std::cout << *x;</pre>
<hr>
<p>
$Date: 2008-05-19 15:42:39 -0400 (Mon, 19 May 2008) $</p>
<p><small>Copyright 2008 Peter Dimov. Copyright 2008 Frank Mori Hess.
Distributed under the Boost Software License,
Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A>
or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

BIN
msvcspeed.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

105
pointer_cast.html Normal file
View File

@@ -0,0 +1,105 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>pointer_cast.hpp</title>
</head>
<body>
<h1><IMG height="86" alt="C++ Boost" src="../../boost.png" width="277" align="middle" border="0">Pointer
cast functions</h1>
<p>The pointer cast functions (<code>boost::static_pointer_cast</code> <code>boost::dynamic_pointer_cast</code>
<code>boost::reinterpret_pointer_cast</code> <code>boost::const_pointer_cast</code>)
provide a way to write generic pointer castings for raw pointers. The functions
are defined in <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A>.</CITE></p>
<P>There is test/example code in <CITE><A href="test/pointer_cast_test.cpp">pointer_cast_test.cpp</A></CITE>.</p>
<h2><a name="rationale">Rationale</a></h2>
<P>Boost smart pointers usually overload those functions to provide a mechanism to
emulate pointers casts. For example, <code>boost::shared_ptr&lt;...&gt;</code> implements
a static pointer cast this way:</P>
<pre>
template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; static_pointer_cast(shared_ptr&lt;U&gt; const &amp;r);
</pre>
<P>Pointer cast functions from <CITE><A href="../../boost/pointer_cast.hpp">boost/pointer_cast.hpp</A></CITE>
are overloads of <code>boost::static_pointer_cast</code>, <code>boost::dynamic_pointer_cast</code>,
<code>boost::reinterpret_pointer_cast</code> and <code>boost::const_pointer_cast</code>
for raw pointers. This way when developing pointer type independent classes,
for example, memory managers or shared memory compatible classes, the same code
can be used for raw and smart pointers.</p>
<H2><A name="synopsis">Synopsis</A></H2>
<BLOCKQUOTE>
<PRE>
namespace boost {
template&lt;class T, class U&gt;
inline T* static_pointer_cast(U *ptr)
{ return static_cast&lt;T*&gt;(ptr); }
template&lt;class T, class U&gt;
inline T* dynamic_pointer_cast(U *ptr)
{ return dynamic_cast&lt;T*&gt;(ptr); }
template&lt;class T, class U&gt;
inline T* const_pointer_cast(U *ptr)
{ return const_cast&lt;T*&gt;(ptr); }
template&lt;class T, class U&gt;
inline T* reinterpret_pointer_cast(U *ptr)
{ return reinterpret_cast&lt;T*&gt;(ptr); }
} // namespace boost
</PRE>
</BLOCKQUOTE>
<P>As you can see from the above synopsis, the pointer cast functions are just
wrappers around standard C++ cast operators.</P>
<H2><A name="example">Example</A></H2>
<BLOCKQUOTE>
<PRE>
#include &lt;boost/pointer_cast.hpp&gt;
#include &lt;boost/shared_ptr.hpp&gt;
class base
{
public:
virtual ~base()
{
}
};
class derived: public base
{
};
template &lt;class BasePtr&gt;
void check_if_it_is_derived(const BasePtr &amp;ptr)
{
assert(boost::dynamic_pointer_cast&lt;derived&gt;(ptr) != 0);
}
int main()
{
<I>// Create a raw and a shared_ptr</I>
base *ptr = new derived;
boost::shared_ptr&lt;base&gt; sptr(new derived);
<I>// Check that base pointer points actually to derived class</I>
check_if_it_is_derived(ptr);
check_if_it_is_derived(sptr);
// <EM>Ok!</EM>
delete ptr;
return 0;
}</PRE>
</BLOCKQUOTE>
<P>The example demonstrates how the generic pointer casts help us create pointer
independent code.</P>
<hr>
<p>Revised: $Date$</p>
<p>Copyright 2005 Ion Gazta<74>aga. Use, modification, and distribution are subject to
the Boost Software License, Version 1.0. (See accompanying file <A href="../../LICENSE_1_0.txt">
LICENSE_1_0.txt</A> or a copy at &lt;<A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>&gt;.)</p>
</body>
</html>

108
pointer_to_other.html Normal file
View File

@@ -0,0 +1,108 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>pointer_to_other.hpp</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff" text="#000000">
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" WIDTH="277" HEIGHT="86">Header
<a href="../../boost/pointer_to_other.hpp">boost/pointer_to_other.hpp</a></h1>
<p>
The pointer to other utility provides a way, given a source pointer type,
to obtain a pointer of the same type to another pointee type. The utility is
defined in <cite><a href="../../boost/pointer_to_other.hpp">boost/pointer_to_other.hpp</a>.</cite></p>
<p>There is test/example code in <cite><a href="test/pointer_to_other_test.cpp">pointer_to_other_test.cpp</a></cite>.</p>
<h2><a name="contents">Contents</a></h2>
<ul>
<li>
<a href="#rationale">Rationale</a>
<li>
<a href="#synopsis">Synopsis</a>
<li>
<a href="#example">Example</a></li>
</ul>
<h2><a name="rationale">Rationale</a></h2>
<p>When building pointer independent classes, like memory managers, allocators, or
containers, there is often a need to define pointers generically, so that if a
template parameter represents a pointer (for example, a raw or smart pointer to
an int), we can define another pointer of the same type to another pointee (a
raw or smart pointer to a float.)</p>
<pre>template &lt;class IntPtr&gt;
class FloatPointerHolder
{
<em>// Let's define a pointer to a float</em>
typedef typename boost::pointer_to_other
&lt;IntPtr, float&gt;::type float_ptr_t;
float_ptr_t float_ptr;
};</pre>
<h2><a name="synopsis">Synopsis</a></h2>
<pre>
namespace boost {
template&lt;class T, class U&gt;
struct pointer_to_other;
template&lt;class T, class U, template &lt;class&gt; class Sp&gt;
struct pointer_to_other&lt; Sp&lt;T&gt;, U &gt;
{
typedef Sp&lt;U&gt; type;
};
template&lt;class T, class T2, class U,
template &lt;class, class&gt; class Sp&gt;
struct pointer_to_other&lt; Sp&lt;T, T2&gt;, U &gt;
{
typedef Sp&lt;U, T2&gt; type;
};
template&lt;class T, class T2, class T3, class U,
template &lt;class, class, class&gt; class Sp&gt;
struct pointer_to_other&lt; Sp&lt;T, T2, T3&gt;, U &gt;
{
typedef Sp&lt;U, T2, T3&gt; type;
};
template&lt;class T, class U&gt;
struct pointer_to_other&lt; T*, U &gt;
{
typedef U* type;
};
} <em>// namespace boost</em></pre>
<p>If these definitions are not correct for a specific smart pointer, we can define
a specialization of pointer_to_other.</p>
<h2><a name="example">Example</a></h2>
<pre><em>// Let's define a memory allocator that can
// work with raw and smart pointers</em>
#include &lt;boost/pointer_to_other.hpp&gt;
template &lt;class VoidPtr&gt;
class memory_allocator
{<em>
// Predefine a memory_block </em>
struct block;<em>
// Define a pointer to a memory_block from a void pointer
// If VoidPtr is void *, block_ptr_t is block*
// If VoidPtr is smart_ptr&lt;void&gt;, block_ptr_t is smart_ptr&lt;block&gt;</em>
typedef typename boost::pointer_to_other
&lt;VoidPtr, block&gt;::type block_ptr_t;
struct block
{
std::size_t size;
block_ptr_t next_block;
};
block_ptr_t free_blocks;
};</pre>
<p>As we can see, using pointer_to_other we can create pointer independent code.</p>
<hr>
<p>Last revised: $Date$</p>
<p><small>Copyright 2005, 2006 Ion Gazta<74>aga and Peter Dimov. Use, modification,
and distribution are subject to the Boost Software License, Version 1.0.<br>
(See accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a
copy at &lt; <a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>&gt;.)</small></p>
</body>
</html>

116
scoped_array.htm Normal file
View File

@@ -0,0 +1,116 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>scoped_array</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff" text="#000000">
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
border="0"></A>scoped_array class template</h1>
<p>The <b>scoped_array</b> class template stores a pointer to a dynamically
allocated array. (Dynamically allocated arrays are allocated with the C++ <b>new[]</b>
expression.) The array pointed to is guaranteed to be deleted, either on
destruction of the <b>scoped_array</b>, or via an explicit <b>reset</b>.</p>
<p>The <b>scoped_array</b> template is a simple solution for simple needs. It
supplies a basic "resource acquisition is initialization" facility, without
shared-ownership or transfer-of-ownership semantics. Both its name and
enforcement of semantics (by being <a href="../utility/utility.htm#Class_noncopyable">
noncopyable</a>) signal its intent to retain ownership solely within the
current scope. Because it is <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>,
it is safer than <b>shared_array</b> for pointers which should not be copied.</p>
<p>Because <b>scoped_array</b> is so simple, in its usual implementation every
operation is as fast as a built-in array pointer and it has no more space
overhead that a built-in array pointer.</p>
<p>It cannot be used in C++ standard library containers. See <a href="shared_array.htm">
<b>shared_array</b></a> if <b>scoped_array</b> does not meet your needs.</p>
<p>It cannot correctly hold a pointer to a single object. See <a href="scoped_ptr.htm"><b>scoped_ptr</b></a>
for that usage.</p>
<p>A <b>std::vector</b> is an alternative to a <b>scoped_array</b> that is a bit
heavier duty but far more flexible. A <b>boost::array</b> is an alternative
that does not use dynamic allocation.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p>
<h2>Synopsis</h2>
<pre>namespace boost {
template&lt;class T&gt; class scoped_array : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> {
public:
typedef T <a href="#element_type">element_type</a>;
explicit <a href="#ctor">scoped_array</a>(T * p = 0); // never throws
<a href="#destructor">~scoped_array</a>(); // never throws
void <a href="#reset">reset</a>(T * p = 0); // never throws
T &amp; <a href="#operator[]">operator[]</a>(std::ptrdiff_t i) const; // never throws
T * <a href="#get">get</a>() const; // never throws
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
void <a href="#swap">swap</a>(scoped_array &amp; b); // never throws
};
template&lt;class T&gt; void <a href="#free-swap">swap</a>(scoped_array&lt;T&gt; &amp; a, scoped_array&lt;T&gt; &amp; b); // never throws
}</pre>
<h2>Members</h2>
<h3>
<a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre>
<p>Provides the type of the stored pointer.</p>
<h3><a name="ctor">constructors</a></h3>
<pre>explicit scoped_array(T * p = 0); // never throws</pre>
<p>Constructs a <b>scoped_array</b>, storing a copy of <b>p</b>, which must have
been allocated via a C++ <b>new</b>[] expression or be 0. <b>T</b> is not
required be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p>
<h3><a name="destructor">destructor</a></h3>
<pre>~scoped_array(); // never throws</pre>
<p>Deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on
a pointer with a value of 0 is harmless. The guarantee that this does not throw
exceptions depends on the requirement that the deleted array's objects'
destructors do not throw exceptions. See the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p>
<h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0); // never throws</pre>
<p>
Deletes the array pointed to by the stored pointer and then stores a copy of p,
which must have been allocated via a C++ <b>new[]</b> expression or be 0. The
guarantee that this does not throw exceptions depends on the requirement that
the deleted array's objects' destructors do not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="operator[]">subscripting</a></h3>
<pre>T &amp; operator[](std::ptrdiff_t i) const; // never throws</pre>
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored
pointer. Behavior is undefined and almost certainly undesirable if the stored
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the
number of elements in the array.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
to <code>get() != 0</code>.</p>
<h3><a name="swap">swap</a></h3>
<pre>void swap(scoped_array &amp; b); // never throws</pre>
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt; void swap(scoped_array&lt;T&gt; &amp; a, scoped_array&lt;T&gt; &amp; b); // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
Provided as an aid to generic programming.</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan-->
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310"--></p>
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

181
scoped_ptr.htm Normal file
View File

@@ -0,0 +1,181 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>scoped_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff" text="#000000">
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
border="0"></A>scoped_ptr class template</h1>
<p>The <b>scoped_ptr</b> class template stores a pointer to a dynamically allocated
object. (Dynamically allocated objects are allocated with the C++ <b>new</b> expression.)
The object pointed to is guaranteed to be deleted, either on destruction of the <b>scoped_ptr</b>,
or via an explicit <b>reset</b>. See the <a href="#example">example</a>.</p>
<p>The <b>scoped_ptr</b> template is a simple solution for simple needs. It
supplies a basic "resource acquisition is initialization" facility, without
shared-ownership or transfer-of-ownership semantics. Both its name and
enforcement of semantics (by being <a href="../utility/utility.htm#Class_noncopyable">
noncopyable</a>) signal its intent to retain ownership solely within the
current scope. Because it is <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a>,
it is safer than <b>shared_ptr</b> or <b>std::auto_ptr</b> for pointers which
should not be copied.</p>
<p>Because <b>scoped_ptr</b> is simple, in its usual implementation every operation
is as fast as for a built-in pointer and it has no more space overhead that a
built-in pointer.</p>
<p><STRONG>scoped_ptr</STRONG> cannot be used in C++ Standard Library containers.
Use <a href="shared_ptr.htm"><b>shared_ptr</b></a> if you need a smart pointer
that can.</p>
<p><STRONG>scoped_ptr</STRONG> cannot correctly hold a pointer to a dynamically
allocated array. See <a href="scoped_array.htm"><b>scoped_array</b></a> for
that usage.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p>
<h2>Synopsis</h2>
<pre>namespace boost {
template&lt;class T&gt; class scoped_ptr : <a href="../utility/utility.htm#Class_noncopyable">noncopyable</a> {
public:
typedef T <a href="#element_type">element_type</a>;
explicit <a href="#constructors">scoped_ptr</a>(T * p = 0); // never throws
<a href="#destructor">~scoped_ptr</a>(); // never throws
void <a href="#reset">reset</a>(T * p = 0); // never throws
T &amp; <a href="#indirection">operator*</a>() const; // never throws
T * <a href="#indirection">operator-&gt;</a>() const; // never throws
T * <a href="#get">get</a>() const; // never throws
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
void <a href="#swap">swap</a>(scoped_ptr &amp; b); // never throws
};
template&lt;class T&gt; void <a href="#free-swap">swap</a>(scoped_ptr&lt;T&gt; &amp; a, scoped_ptr&lt;T&gt; &amp; b); // never throws
}</pre>
<h2>Members</h2>
<h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre>
<p>Provides the type of the stored pointer.</p>
<h3><a name="constructors">constructors</a></h3>
<pre>explicit scoped_ptr(T * p = 0); // never throws</pre>
<p>Constructs a <b>scoped_ptr</b>, storing a copy of <b>p</b>, which must have been
allocated via a C++ <b>new</b> expression or be 0. <b>T</b> is not required be
a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p>
<h3><a name="destructor">destructor</a></h3>
<pre>~scoped_ptr(); // never throws</pre>
<p>Destroys the object pointed to by the stored pointer, if any, as if by using <tt>delete
this-&gt;get()</tt>.</p>
<P>
The guarantee that this does not throw exceptions depends on the requirement
that the deleted object's destructor does not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</P>
<h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0); // never throws</pre>
<p>
Deletes the object pointed to by the stored pointer and then stores a copy of
p, which must have been allocated via a C++ <b>new</b> expression or be 0. The
guarantee that this does not throw exceptions depends on the requirement that
the deleted object's destructor does not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="indirection">indirection</a></h3>
<pre>T &amp; operator*() const; // never throws</pre>
<p>Returns a reference to the object pointed to by the stored pointer. Behavior is
undefined if the stored pointer is 0.</p>
<pre>T * operator-&gt;() const; // never throws</pre>
<p>Returns the stored pointer. Behavior is undefined if the stored pointer is 0.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
to <code>get() != 0</code>.</p>
<h3><a name="swap">swap</a></h3>
<pre>void swap(scoped_ptr &amp; b); // never throws</pre>
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt; void swap(scoped_ptr&lt;T&gt; &amp; a, scoped_ptr&lt;T&gt; &amp; b); // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
Provided as an aid to generic programming.</p>
<h2><a name="example">Example</a></h2>
<p>Here's an example that uses <b>scoped_ptr</b>.</p>
<blockquote>
<pre>#include &lt;boost/scoped_ptr.hpp&gt;
#include &lt;iostream&gt;
struct Shoe { ~Shoe() { std::cout &lt;&lt; "Buckle my shoe\n"; } };
class MyClass {
boost::scoped_ptr&lt;int&gt; ptr;
public:
MyClass() : ptr(new int) { *ptr = 0; }
int add_one() { return ++*ptr; }
};
int main()
{
boost::scoped_ptr&lt;Shoe&gt; x(new Shoe);
MyClass my_instance;
std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n';
std::cout &lt;&lt; my_instance.add_one() &lt;&lt; '\n';
}</pre>
</blockquote>
<p>The example program produces the beginning of a child's nursery rhyme:</p>
<blockquote>
<pre>1
2
Buckle my shoe</pre>
</blockquote>
<h2>Rationale</h2>
<p>The primary reason to use <b>scoped_ptr</b> rather than <b>auto_ptr</b> is to
let readers of your code know that you intend "resource acquisition is
initialization" to be applied only for the current scope, and have no intent to
transfer ownership.</p>
<p>A secondary reason to use <b>scoped_ptr</b> is to prevent a later maintenance
programmer from adding a function that transfers ownership by returning the <b>auto_ptr</b>,
because the maintenance programmer saw <b>auto_ptr</b>, and assumed ownership
could safely be transferred.</p>
<p>Think of <b>bool</b> vs <b>int</b>. We all know that under the covers <b>bool</b>
is usually just an <b>int</b>. Indeed, some argued against including <b>bool</b>
in the C++ standard because of that. But by coding <b>bool</b> rather than <b>int</b>,
you tell your readers what your intent is. Same with <b>scoped_ptr</b>; by
using it you are signaling intent.</p>
<p>It has been suggested that <b>scoped_ptr&lt;T&gt;</b> is equivalent to <b>std::auto_ptr&lt;T&gt;
const</b>. Ed Brey pointed out, however, that <b>reset</b> will not work on
a <b>std::auto_ptr&lt;T&gt; const.</b></p>
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
<p>One common usage of <b>scoped_ptr</b> is to implement a handle/body (also called
pimpl) idiom which avoids exposing the body (implementation) in the header
file.</p>
<p>The <a href="example/scoped_ptr_example_test.cpp">scoped_ptr_example_test.cpp</a>
sample program includes a header file, <a href="example/scoped_ptr_example.hpp">scoped_ptr_example.hpp</a>,
which uses a <b>scoped_ptr&lt;&gt;</b> to an incomplete type to hide the
implementation. The instantiation of member functions which require a complete
type occurs in the <a href="example/scoped_ptr_example.cpp">scoped_ptr_example.cpp</a>
implementation file.</p>
<h2>Frequently Asked Questions</h2>
<p><b>Q</b>. Why doesn't <b>scoped_ptr</b> have a release() member?<br>
<b>A</b>. When reading source code, it is valuable to be able to draw
conclusions about program behavior based on the types being used. If <STRONG>scoped_ptr</STRONG>
had a release() member, it would become possible to transfer ownership of the
held pointer, weakening its role as a way of limiting resource lifetime to a
given context. Use <STRONG>std::auto_ptr</STRONG> where transfer of ownership
is required. (supplied by Dave Abrahams)</p>
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310" --></p>
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

185
shared_array.htm Normal file
View File

@@ -0,0 +1,185 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>shared_array</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff" text="#000000">
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
border="0"></A>shared_array class template</h1>
<p>The <b>shared_array</b> class template stores a pointer to a dynamically
allocated array. (Dynamically allocated array are allocated with the C++ <b>new[]</b>
expression.) The object pointed to is guaranteed to be deleted when the last <b>shared_array</b>
pointing to it is destroyed or reset.</p>
<p>Every <b>shared_array</b> meets the <b>CopyConstructible</b> and <b>Assignable</b>
requirements of the C++ Standard Library, and so can be used in standard
library containers. Comparison operators are supplied so that <b>shared_array</b>
works with the standard library's associative containers.</p>
<p>Normally, a <b>shared_array</b> cannot correctly hold a pointer to an object
that has been allocated with the non-array form of <STRONG>new</STRONG>. See <a href="shared_ptr.htm">
<b>shared_ptr</b></a> for that usage.</p>
<p>Because the implementation uses reference counting, cycles of <b>shared_array</b>
instances will not be reclaimed. For example, if <b>main()</b> holds a <b>shared_array</b>
to <b>A</b>, which directly or indirectly holds a <b>shared_array</b> back to <b>A</b>,
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_array</b>
will leave <b>A</b> dangling with a use count of 1.</p>
<p>A <b>shared_ptr</b> to a <b>std::vector</b> is an alternative to a <b>shared_array</b>
that is a bit heavier duty but far more flexible.</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <b>T</b> must meet the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p>
<h2>Synopsis</h2>
<pre>namespace boost {
template&lt;class T&gt; class shared_array {
public:
typedef T <a href="#element_type">element_type</a>;
explicit <a href="#constructors">shared_array</a>(T * p = 0);
template&lt;class D&gt; <a href="#constructors">shared_array</a>(T * p, D d);
<a href="#destructor">~shared_array</a>(); // never throws
<a href="#constructors">shared_array</a>(shared_array const &amp; r); // never throws
shared_array &amp; <a href="#assignment">operator=</a>(shared_array const &amp; r); // never throws
void <a href="#reset">reset</a>(T * p = 0);
template&lt;class D&gt; void <a href="#reset">reset</a>(T * p, D d);
T &amp; <a href="#indexing">operator[]</a>(std::ptrdiff_t i) const; // never throws
T * <a href="#get">get</a>() const; // never throws
bool <a href="#unique">unique</a>() const; // never throws
long <a href="#use_count">use_count</a>() const; // never throws
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
void <a href="#swap">swap</a>(shared_array&lt;T&gt; &amp; b); // never throws
};
template&lt;class T&gt;
bool <a href="#comparison">operator==</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt;
bool <a href="#comparison">operator!=</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt;
bool <a href="#comparison">operator&lt;</a>(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt; void <a href="#free-swap">swap</a>(shared_array&lt;T&gt; &amp; a, shared_array&lt;T&gt; &amp; b); // never throws
}</pre>
<h2>Members</h2>
<h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre>
<p>Provides the type of the stored pointer.</p>
<h3><a name="constructors">constructors</a></h3>
<pre>explicit shared_array(T * p = 0);</pre>
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b>, which must be a
pointer to an array that was allocated via a C++ <b>new[]</b> expression or be
0. Afterwards, the <a href="#use_count">use count</a> is 1 (even if p == 0; see <a href="#destructor">
~shared_array</a>). The only exception which may be thrown by this
constructor is <b>std::bad_alloc</b>. If an exception is thrown, <b>delete[] p</b>
is called.</p>
<pre>template&lt;class D&gt; shared_array(T * p, D d);</pre>
<p>Constructs a <b>shared_array</b>, storing a copy of <b>p</b> and of <b>d</b>.
Afterwards, the <a href="#use_count">use count</a> is 1. <b>D</b>'s copy
constructor and destructor must not throw. When the the time comes to delete
the array pointed to by <b>p</b>, the object <b>d</b> is used in the statement <b>d(p)</b>.
Invoking the object <b>d</b> with parameter <b>p</b> in this way must not
throw. The only exception which may be thrown by this constructor is <b>std::bad_alloc</b>.
If an exception is thrown, <b>d(p)</b> is called.</p>
<pre>shared_array(shared_array const &amp; r); // never throws</pre>
<p>Constructs a <b>shared_array</b>, as if by storing a copy of the pointer stored
in <b>r</b>. Afterwards, the <a href="#use_count">use count</a> for all copies
is 1 more than the initial use count.</p>
<h3><a name="destructor">destructor</a></h3>
<pre>~shared_array(); // never throws</pre>
<p>Decrements the <a href="#use_count">use count</a>. Then, if the use count is 0,
deletes the array pointed to by the stored pointer. Note that <b>delete[]</b> on
a pointer with a value of 0 is harmless. <b>T</b> need not be a complete type.
The guarantee that this does not throw exceptions depends on the requirement
that the deleted object's destructor does not throw exceptions. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="assignment">assignment</a></h3>
<pre>shared_array &amp; operator=(shared_array const &amp; r); // never throws</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_array</b> with the new one, destroying the
replaced object.</p>
<h3><a name="reset">reset</a></h3>
<pre>void reset(T * p = 0);</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_array</b> with the new one, destroying the
replaced object. The only exception which may be thrown is <b>std::bad_alloc</b>.
If an exception is thrown, <b>delete[] p</b> is called.</p>
<pre>template&lt;class D&gt; void reset(T * p, D d);</pre>
<p>Constructs a new <b>shared_array</b> as described <a href="#constructors">above</a>,
then replaces this <b>shared_array</b> with the new one, destroying the
replaced object. <b>D</b>'s copy constructor must not throw. The only exception
which may be thrown is <b>std::bad_alloc</b>. If an exception is thrown, <b>d(p)</b>
is called.</p>
<h3><a name="indexing">indexing</a></h3>
<pre>T &amp; operator[](std::ptrdiff_t i) const; // never throws</pre>
<p>Returns a reference to element <b>i</b> of the array pointed to by the stored
pointer. Behavior is undefined and almost certainly undesirable if the stored
pointer is 0, or if <b>i</b> is less than 0 or is greater than or equal to the
number of elements in the array.</p>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<p>Returns the stored pointer. <b>T</b> need not be a complete type. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="unique">unique</a></h3>
<pre>bool unique() const; // never throws</pre>
<p>Returns true if no other <b>shared_array</b> is sharing ownership of the stored
pointer, false otherwise. <b>T</b> need not be a complete type. See the smart
pointer <a href="smart_ptr.htm#common_requirements">common requirements</a>.</p>
<h3><a name="use_count">use_count</a></h3>
<pre>long use_count() const; // never throws</pre>
<p>Returns the number of <b>shared_array</b> objects sharing ownership of the
stored pointer. <b>T</b> need not be a complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">
common requirements</a>.</p>
<p>Because <b>use_count</b> is not necessarily efficient to implement for
implementations of <b>shared_array</b> that do not use an explicit reference
count, it might be removed from some future version. Thus it should be used for
debugging purposes only, and not production code.</p>
<h3><a name="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<p>Returns an unspecified value that, when used in boolean contexts, is equivalent
to <code>get() != 0</code>.</p>
<h3><a name="swap">swap</a></h3>
<pre>void swap(shared_ptr &amp; b); // never throws</pre>
<p>Exchanges the contents of the two smart pointers. <b>T</b> need not be a
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3>
<pre>template&lt;class T&gt;
bool operator==(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt;
bool operator!=(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws
template&lt;class T&gt;
bool operator&lt;(shared_array&lt;T&gt; const &amp; a, shared_array&lt;T&gt; const &amp; b); // never throws</pre>
<p>Compares the stored pointers of the two smart pointers. <b>T</b> need not be a
complete type. See the smart pointer <a href="smart_ptr.htm#common_requirements">common
requirements</a>.</p>
<p>The <b>operator&lt;</b> overload is provided to define an ordering so that <b>shared_array</b>
objects can be used in associative containers such as <b>std::map</b>. The
implementation uses <b>std::less&lt;T *&gt;</b> to perform the comparison. This
ensures that the comparison is handled correctly, since the standard mandates
that relational operations on pointers are unspecified (5.9 [expr.rel]
paragraph 2) but <b>std::less&lt;&gt;</b> on pointers is well-defined (20.3.3
[lib.comparisons] paragraph 8).</p>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt;
void swap(shared_array&lt;T&gt; &amp; a, shared_array&lt;T&gt; &amp; b) // never throws</pre>
<p>Equivalent to <b>a.swap(b)</b>. Matches the interface of <b>std::swap</b>.
Provided as an aid to generic programming.</p>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->
09 January 2003<!--webbot bot="Timestamp" endspan i-checksum="32310" --></p>
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

722
shared_ptr.htm Normal file
View File

@@ -0,0 +1,722 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>shared_ptr</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body text="#000000" bgColor="#ffffff">
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
border="0"></A>shared_ptr class template</h1>
<p><A href="#Introduction">Introduction</A><br>
<A href="#BestPractices">Best Practices</A><br>
<A href="#Synopsis">Synopsis</A><br>
<A href="#Members">Members</A><br>
<A href="#functions">Free Functions</A><br>
<A href="#example">Example</A><br>
<A href="#Handle/Body">Handle/Body Idiom</A><br>
<A href="#ThreadSafety">Thread Safety</A><br>
<A href="#FAQ">Frequently Asked Questions</A><br>
<A href="smarttests.htm">Smart Pointer Timings</A><br>
<A href="sp_techniques.html">Programming Techniques</A></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <b>shared_ptr</b> class template stores a pointer to a dynamically allocated
object, typically with a C++ <EM>new-expression</EM>. The object pointed to is
guaranteed to be deleted when the last <b>shared_ptr</b> pointing to it is
destroyed or reset. See the <A href="#example">example</A>.</p>
<p>Every <b>shared_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b>
requirements of the C++ Standard Library, and so can be used in standard
library containers. Comparison operators are supplied so that <b>shared_ptr</b>
works with the standard library's associative containers.</p>
<p>Normally, a <b>shared_ptr</b> cannot correctly hold a pointer to a dynamically
allocated array. See <A href="shared_array.htm"><b>shared_array</b></A> for
that usage.</p>
<p>Because the implementation uses reference counting, cycles of <b>shared_ptr</b> instances
will not be reclaimed. For example, if <b>main()</b> holds a <b>shared_ptr</b> to
<b>A</b>, which directly or indirectly holds a <b>shared_ptr</b> back to <b>A</b>,
<b>A</b>'s use count will be 2. Destruction of the original <b>shared_ptr</b> will
leave <b>A</b> dangling with a use count of 1. Use <A href="weak_ptr.htm">weak_ptr</A>
to "break cycles."</p>
<p>The class template is parameterized on <b>T</b>, the type of the object pointed
to. <STRONG>shared_ptr</STRONG> and most of its member functions place no
requirements on <STRONG>T</STRONG>; it is allowed to be an incomplete type, or <STRONG>
void</STRONG>. Member functions that do place additional requirements (<A href="#constructors">constructors</A>,
<A href="#reset">reset</A>) are explicitly documented below.</p>
<P><STRONG>shared_ptr&lt;T&gt;</STRONG> can be implicitly converted to <STRONG>shared_ptr&lt;U&gt;</STRONG>
whenever <STRONG>T*</STRONG> can be implicitly converted to <STRONG>U*</STRONG>.
In particular, <STRONG>shared_ptr&lt;T&gt;</STRONG> is implicitly convertible
to <STRONG>shared_ptr&lt;T const&gt;</STRONG>, to <STRONG>shared_ptr&lt;U&gt;</STRONG>
where <STRONG>U</STRONG> is an accessible base of <STRONG>T</STRONG>, and to <STRONG>
shared_ptr&lt;void&gt;</STRONG>.</P>
<P><STRONG>shared_ptr</STRONG> is now part of <STRONG>TR1</STRONG>, the first C++
Library Technical Report. The latest draft of <STRONG>TR1</STRONG> is available
at the following location:</P>
<P><A href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf">http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1745.pdf</A>
(1.36Mb PDF)</P>
<P>This implementation conforms to the TR1 specification, with the only exception
that it resides in namespace <code>boost</code> instead of <code>std::tr1</code>.</P>
<h2><a name="BestPractices">Best Practices</a></h2>
<P>A simple guideline that nearly eliminates the possibility of memory leaks is:
always use a named smart pointer variable to hold the result of <STRONG>new. </STRONG>
Every occurence of the <STRONG>new</STRONG> keyword in the code should have the
form:</P>
<PRE>shared_ptr&lt;T&gt; p(new Y);</PRE>
<P>It is, of course, acceptable to use another smart pointer in place of <STRONG>shared_ptr</STRONG>
above; having <STRONG>T</STRONG> and <STRONG>Y</STRONG> be the same type, or
passing arguments to <STRONG>Y</STRONG>'s constructor is also OK.</P>
<P>If you observe this guideline, it naturally follows that you will have no
explicit <STRONG>delete</STRONG>s; <STRONG>try/catch</STRONG> constructs will
be rare.</P>
<P>Avoid using unnamed <STRONG>shared_ptr</STRONG> temporaries to save typing; to
see why this is dangerous, consider this example:</P>
<PRE>void f(shared_ptr&lt;int&gt;, int);
int g();
void ok()
{
shared_ptr&lt;int&gt; p(new int(2));
f(p, g());
}
void bad()
{
f(shared_ptr&lt;int&gt;(new int(2)), g());
}
</PRE>
<P>The function <STRONG>ok</STRONG> follows the guideline to the letter, whereas <STRONG>
bad</STRONG> constructs the temporary <STRONG>shared_ptr</STRONG> in place,
admitting the possibility of a memory leak. Since function arguments are
evaluated in unspecified order, it is possible for <STRONG>new int(2)</STRONG> to
be evaluated first, <STRONG>g()</STRONG> second, and we may never get to the <STRONG>
shared_ptr </STRONG>constructor if <STRONG>g</STRONG> throws an exception.
See <A href="http://www.gotw.ca/gotw/056.htm">Herb Sutter's treatment</A> (also <A href="http://www.cuj.com/reference/articles/2002/0212/0212_sutter.htm">
here</A>) of the issue for more information.</P>
<P>The exception safety problem described above may also be eliminated by using
the <a href="make_shared.html"><code>make_shared</code></a>
or <a href="make_shared.html"><code>allocate_shared</code></a>
factory functions defined in boost/make_shared.hpp. These factory functions also provide
an efficiency benefit by consolidating allocations.<P>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost {
class bad_weak_ptr: public std::exception;
template&lt;class T&gt; class <A href="weak_ptr.htm" >weak_ptr</A>;
template&lt;class T&gt; class shared_ptr {
public:
typedef T <A href="#element_type" >element_type</A>;
<A href="#constructors" >shared_ptr</A>(); // never throws
template&lt;class Y&gt; explicit <A href="#constructors" >shared_ptr</A>(Y * p);
template&lt;class Y, class D&gt; <A href="#constructors" >shared_ptr</A>(Y * p, D d);
template&lt;class Y, class D, class A&gt; <A href="#allocator_constructor" >shared_ptr</A>(Y * p, D d, A a);
<A href="#destructor" >~shared_ptr</A>(); // never throws
<A href="#constructors" >shared_ptr</A>(shared_ptr const &amp; r); // never throws
template&lt;class Y&gt; <A href="#constructors" >shared_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;class Y&gt; <A href="#constructors" >shared_ptr</A>(shared_ptr&lt;Y&gt; const &amp; r, T * p); // never throws
template&lt;class Y&gt; explicit <A href="#constructors" >shared_ptr</A>(<A href="weak_ptr.htm" >weak_ptr</A>&lt;Y&gt; const &amp; r);
template&lt;class Y&gt; explicit <A href="#constructors" >shared_ptr</A>(std::auto_ptr&lt;Y&gt; &amp; r);
shared_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr &amp; <A href="#assignment" >operator=</A>(std::auto_ptr&lt;Y&gt; &amp; r);
void <A href="#reset" >reset</A>(); // never throws
template&lt;class Y&gt; void <A href="#reset" >reset</A>(Y * p);
template&lt;class Y, class D&gt; void <A href="#reset" >reset</A>(Y * p, D d);
template&lt;class Y, class D, class A&gt; void <A href="#reset" >reset</A>(Y * p, D d, A a);
template&lt;class Y&gt; void <A href="#reset" >reset</A>(shared_ptr&lt;Y&gt; const &amp; r, T * p); // never throws
T &amp; <A href="#indirection" >operator*</A>() const; // never throws
T * <A href="#indirection" >operator-&gt;</A>() const; // never throws
T * <A href="#get" >get</A>() const; // never throws
bool <A href="#unique" >unique</A>() const; // never throws
long <A href="#use_count" >use_count</A>() const; // never throws
operator <A href="#conversions" ><i>unspecified-bool-type</i></A>() const; // never throws
void <A href="#swap" >swap</A>(shared_ptr &amp; b); // never throws
};
template&lt;class T, class U&gt;
bool <A href="#comparison" >operator==</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T, class U&gt;
bool <A href="#comparison" >operator!=</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T, class U&gt;
bool <A href="#comparison" >operator&lt;</A>(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws
template&lt;class T&gt; void <A href="#free-swap" >swap</A>(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b); // never throws
template&lt;class T&gt; T * <A href="#get_pointer" >get_pointer</A>(shared_ptr&lt;T&gt; const &amp; p); // never throws
template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; <A href="#static_pointer_cast" >static_pointer_cast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; <A href="#const_pointer_cast" >const_pointer_cast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; <A href="#dynamic_pointer_cast" >dynamic_pointer_cast</A>(shared_ptr&lt;U&gt; const &amp; r); // never throws
template&lt;class E, class T, class Y&gt;
std::basic_ostream&lt;E, T&gt; &amp; <A href="#insertion-operator" >operator&lt;&lt;</A> (std::basic_ostream&lt;E, T&gt; &amp; os, shared_ptr&lt;Y&gt; const &amp; p);
template&lt;class D, class T&gt;
D * <A href="#get_deleter">get_deleter</A>(shared_ptr&lt;T&gt; const &amp; p);
}</pre>
<h2><a name="Members">Members</a></h2>
<h3><a name="element_type">element_type</a></h3>
<pre>typedef T element_type;</pre>
<blockquote>
<p>Provides the type of the template parameter T.</p>
</blockquote>
<h3><a name="constructors">constructors</a></h3>
<pre>shared_ptr(); // never throws</pre>
<blockquote>
<p><b>Effects:</b> Constructs an <EM>empty</EM> <b>shared_ptr</b>.</p>
<p><b>Postconditions:</b> <code>use_count() == 0 &amp;&amp; get() == 0</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<P><EM>[The nothrow guarantee is important, since <STRONG>reset()</STRONG> is specified
in terms of the default constructor; this implies that the constructor must not
allocate memory.]</EM></P>
<pre>template&lt;class Y&gt; explicit shared_ptr(Y * p);</pre>
<blockquote>
<p><b>Requirements:</b> <b>p</b> must be convertible to <b>T *</b>. <STRONG>Y</STRONG>
must be a complete type. The expression <code>delete p</code> must be
well-formed, must not invoke undefined behavior, and must not throw exceptions.
</p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b> that <EM>owns</EM> the pointer <b>p</b>.</p>
<p><b>Postconditions:</b> <code>use_count() == 1 &amp;&amp; get() == p</code>.</p>
<p><b>Throws:</b> <STRONG>std::bad_alloc</STRONG>, or an implementation-defined
exception when a resource other than memory could not be obtained.</p>
<p><b>Exception safety:</b> If an exception is thrown, <code>delete p</code> is
called.</p>
<P><STRONG>Notes:</STRONG> <B>p</B> must be a pointer to an object that was
allocated via a C++ <B>new</B> expression or be 0. The postcondition that <A href="#use_count">
use count</A> is 1 holds even if <b>p</b> is 0; invoking <STRONG>delete</STRONG>
on a pointer that has a value of 0 is harmless.</P>
</blockquote>
<P><EM>[This constructor has been changed to a template in order to remember the actual
pointer type passed. The destructor will call <STRONG>delete</STRONG> with the
same pointer, complete with its original type, even when <STRONG>T</STRONG> does
not have a virtual destructor, or is <STRONG>void</STRONG>.</EM></P>
<P><EM>The optional intrusive counting support has been dropped as it exposes too much
implementation details and doesn't interact well with <STRONG>weak_ptr</STRONG>.
The current implementation uses a different mechanism, <A href="enable_shared_from_this.html">
enable_shared_from_this</A>, to solve the "<STRONG>shared_ptr</STRONG> from <STRONG>
this</STRONG>" problem.</EM><EM>]</EM></P>
<a name="allocator_constructor"></a>
<pre>template&lt;class Y, class D&gt; shared_ptr(Y * p, D d);
template&lt;class Y, class D, class A&gt; shared_ptr(Y * p, D d, A a);</pre>
<blockquote>
<p><b>Requirements:</b> <B>p</B> must be convertible to <B>T *</B>. <STRONG>D</STRONG>
must be <STRONG>CopyConstructible</STRONG>. The copy constructor and destructor
of <b>D</b> must not throw. The expression <code>d(p)</code> must be
well-formed, must not invoke undefined behavior, and must not throw exceptions. <STRONG>
A</STRONG> must be an <EM>Allocator</EM>, as described in section 20.1.5 (<STRONG>Allocator
requirements</STRONG>) of the C++ Standard.
</p>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b> that <EM>owns</EM> the pointer <STRONG>
p</STRONG> and the deleter <b>d</b>. The second constructor allocates
memory using a copy of <STRONG>a</STRONG>.</p>
<p><b>Postconditions:</b> <code>use_count() == 1 &amp;&amp; get() == p</code>.</p>
<p><b>Throws:</b> <STRONG>std::bad_alloc</STRONG>, or an implementation-defined
exception when a resource other than memory could not be obtained.</p>
<p><b>Exception safety:</b> If an exception is thrown, <code>d(p)</code> is called.</p>
<p><b>Notes:</b> When the the time comes to delete the object pointed to by <b>p</b>,
the stored copy of <STRONG>d</STRONG> is invoked with the stored copy of <STRONG>p</STRONG>
as an argument.</p>
</blockquote>
<P><EM>[Custom deallocators allow a factory function returning a <STRONG>shared_ptr</STRONG>
to insulate the user from its memory allocation strategy. Since the deallocator
is not part of the type, changing the allocation strategy does not break source
or binary compatibility, and does not require a client recompilation. For
example, a "no-op" deallocator is useful when returning a <STRONG>shared_ptr</STRONG>
to a statically allocated object, and other variations allow a <STRONG>shared_ptr</STRONG>
to be used as a wrapper for another smart pointer, easing interoperability.</EM></P>
<P><EM>The support for custom deallocators does not impose significant overhead. Other <STRONG>
shared_ptr</STRONG> features still require a deallocator to be kept.</EM></P>
<P><EM>The requirement that the copy constructor of <b>D</b> does not throw comes from
the pass by value. If the copy constructor throws, the pointer is leaked.
Removing the requirement requires a pass by (const) reference.</EM></P>
<P><EM>The main problem with pass by reference lies in its interaction with rvalues. A
const reference may still cause a copy, and will require a const operator(). A
non-const reference won't bind to an rvalue at all. A good solution to this
problem is the rvalue reference proposed in <A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1377.htm">
N1377</A>/<A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm">N1385</A>.]</EM></P>
<pre>shared_ptr(shared_ptr const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr(shared_ptr&lt;Y&gt; const &amp; r); // never throws</pre>
<blockquote>
<p><b>Effects:</b> If <b>r</b> is <EM>empty</EM>, constructs an <EM>empty</EM> <b>shared_ptr</b>;
otherwise, constructs a <b>shared_ptr</b> that <EM>shares ownership</EM> with <b>r</b>.</p>
<p><b>Postconditions:</b> <code>get() == r.get() &amp;&amp; use_count() ==
r.use_count()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class Y&gt; shared_ptr(shared_ptr&lt;Y&gt; const &amp; r, T * p); // never throws</pre>
<blockquote>
<p><b>Effects:</b> constructs a <b>shared_ptr</b> that <EM>shares ownership</EM> with
<b>r</b> and stores <b>p</b>.</p>
<p><b>Postconditions:</b> <code>get() == p &amp;&amp; use_count() == r.use_count()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class Y&gt; explicit shared_ptr(<A href="weak_ptr.htm" >weak_ptr</A>&lt;Y&gt; const &amp; r);</pre>
<blockquote>
<p><b>Effects:</b> Constructs a <b>shared_ptr</b> that <EM>shares ownership</EM> with
<b>r</b> and stores a copy of the pointer stored in <STRONG>r</STRONG>.</p>
<p><b>Postconditions:</b> <code>use_count() == r.use_count()</code>.</p>
<p><b>Throws:</b> <b>bad_weak_ptr</b> when <code>r.use_count() == 0</code>.</p>
<p><b>Exception safety:</b> If an exception is thrown, the constructor has no
effect.</p>
</blockquote>
<pre>template&lt;class Y&gt; shared_ptr(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Constructs a <B>shared_ptr</B>, as if by storing a copy of <STRONG>r.release()</STRONG>.</P>
<p><b>Postconditions:</b> <code>use_count() == 1</code>.</p>
<p><b>Throws:</b> <STRONG>std::bad_alloc</STRONG>, or an implementation-defined
exception when a resource other than memory could not be obtained.</p>
<P><B>Exception safety:</B> If an exception is thrown, the constructor has no
effect.</P>
</BLOCKQUOTE>
<P><EM>[This constructor takes a the source <STRONG>auto_ptr</STRONG> by reference and
not by value, and cannot accept <STRONG>auto_ptr</STRONG> temporaries. This is
by design, as the constructor offers the strong guarantee; an rvalue reference
would solve this problem, too.]</EM></P>
<h3><a name="destructor">destructor</a></h3>
<pre>~shared_ptr(); // never throws</pre>
<BLOCKQUOTE>
<P><B>Effects:</B></P>
<UL>
<LI>
If <STRONG>*this</STRONG> is <EM>empty</EM>, or <EM>shares ownership</EM> with
another <STRONG>shared_ptr</STRONG> instance (<code>use_count() &gt; 1</code>),
there are no side effects.
<LI>
Otherwise, if <STRONG>*this</STRONG> <EM>owns</EM> a pointer <STRONG>p</STRONG>
and a deleter <STRONG>d</STRONG>, <code>d(p)</code>
is called.
<LI>
Otherwise, <STRONG>*this</STRONG> <EM>owns</EM> a pointer <STRONG>p</STRONG>,
and <code>delete p</code> is called.</LI></UL>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<H3><a name="assignment">assignment</a></H3>
<pre>shared_ptr &amp; operator=(shared_ptr const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr &amp; operator=(shared_ptr&lt;Y&gt; const &amp; r); // never throws
template&lt;class Y&gt; shared_ptr &amp; operator=(std::auto_ptr&lt;Y&gt; &amp; r);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(r).swap(*this)</code>.</P>
<P><B>Returns:</B> <code>*this</code>.</P>
<P><B>Notes:</B> The use count updates caused by the temporary object construction
and destruction are not considered observable side effects, and the
implementation is free to meet the effects (and the implied guarantees) via
different means, without creating a temporary. In particular, in the example:</P>
<pre>shared_ptr&lt;int&gt; p(new int);
shared_ptr&lt;void&gt; q(p);
p = p;
q = p;
</pre>
<p>both assignments may be no-ops.</p>
</BLOCKQUOTE>
<h3><a name="reset">reset</a></h3>
<pre>void reset(); // never throws</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr().swap(*this)</code>.</P>
</BLOCKQUOTE>
<pre>template&lt;class Y&gt; void reset(Y * p);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p).swap(*this)</code>.</P>
</BLOCKQUOTE>
<pre>template&lt;class Y, class D&gt; void reset(Y * p, D d);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d).swap(*this)</code>.</P>
</BLOCKQUOTE>
<pre>template&lt;class Y, class D, class A&gt; void reset(Y * p, D d, A a);</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(p, d, a).swap(*this)</code>.</P>
</BLOCKQUOTE>
<pre>template&lt;class Y&gt; void reset(shared_ptr&lt;Y&gt; const &amp; r, T * p); // never throws</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>shared_ptr(r, p).swap(*this)</code>.</P>
</BLOCKQUOTE>
<h3><a name="indirection">indirection</a></h3>
<pre>T &amp; operator*() const; // never throws</pre>
<blockquote>
<p><b>Requirements:</b> The stored pointer must not be 0.</p>
<p><b>Returns:</b> a reference to the object pointed to by the stored pointer.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>T * operator-&gt;() const; // never throws</pre>
<blockquote>
<p><b>Requirements:</b> The stored pointer must not be 0.</p>
<p><b>Returns:</b> the stored pointer.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h3><a name="get">get</a></h3>
<pre>T * get() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> the stored pointer.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h3><a name="unique">unique</a></h3>
<pre>bool unique() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>use_count() == 1</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <code>unique()</code> may be faster than <code>use_count()</code>.
If you are using <code>unique()</code> to implement copy on write, do not rely
on a specific value when the stored pointer is zero.</P>
</blockquote>
<h3><a name="use_count">use_count</a></h3>
<pre>long use_count() const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> the number of <b>shared_ptr</b> objects, <STRONG>*this</STRONG> included,
that <i>share ownership</i> with <b>*this</b>, or 0 when <STRONG>*this</STRONG>
is <EM>empty</EM>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <code>use_count()</code> is not necessarily efficient. Use only
for debugging and testing purposes, not for production code.</P>
</blockquote>
<h3><a name="conversions">conversions</a></h3>
<pre>operator <i>unspecified-bool-type</i> () const; // never throws</pre>
<blockquote>
<p><b>Returns:</b> an unspecified value that, when used in boolean contexts, is
equivalent to <code>get() != 0</code>.</p>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> This conversion operator allows <b>shared_ptr</b> objects to be
used in boolean contexts, like <code>if (p &amp;&amp; p-&gt;valid()) {}</code>.
The actual target type is typically a pointer to a member function, avoiding
many of the implicit conversion pitfalls.</P>
</blockquote>
<P><EM>[The conversion to bool is not merely syntactic sugar. It allows <STRONG>shared_ptr</STRONG>s
to be declared in conditions when using <A href="#dynamic_pointer_cast">dynamic_pointer_cast</A>
or <A href="weak_ptr.htm#lock">weak_ptr::lock</A>.]</EM></P>
<h3><a name="swap">swap</a></h3>
<pre>void swap(shared_ptr &amp; b); // never throws</pre>
<blockquote>
<p><b>Effects:</b> Exchanges the contents of the two smart pointers.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<h2><a name="functions">Free Functions</a></h2>
<h3><a name="comparison">comparison</a></h3>
<pre>template&lt;class T, class U&gt;
bool operator==(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() == b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T, class U&gt;
bool operator!=(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> <code>a.get() != b.get()</code>.</p>
<p><b>Throws:</b> nothing.</p>
</blockquote>
<pre>template&lt;class T, class U&gt;
bool operator&lt;(shared_ptr&lt;T&gt; const &amp; a, shared_ptr&lt;U&gt; const &amp; b); // never throws</pre>
<blockquote>
<p><b>Returns:</b> an unspecified value such that</p>
<UL>
<LI>
<b>operator&lt;</b> is a strict weak ordering as described in section 25.3 <code>[lib.alg.sorting]</code>
of the C++ standard;
<LI>
under the equivalence relation defined by <STRONG>operator&lt;</STRONG>, <code>!(a
&lt; b) &amp;&amp; !(b &lt; a)</code>, two <STRONG>shared_ptr</STRONG> instances
are equivalent if and only if they <EM>share ownership</EM> or are both <EM>empty</EM>.</LI></UL>
<p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> Allows <STRONG>shared_ptr</STRONG> objects to be used as keys in
associative containers.</P>
</blockquote>
<P><EM>[<STRONG>Operator&lt;</STRONG> has been preferred over a <STRONG>std::less </STRONG>
specialization for consistency and legality reasons, as <STRONG>std::less</STRONG>
is required to return the results of <STRONG>operator&lt;</STRONG>, and many
standard algorithms use <STRONG>operator&lt;</STRONG> instead of <STRONG>std::less</STRONG>
for comparisons when a predicate is not supplied. Composite objects, like <STRONG>std::pair</STRONG>,
also implement their <STRONG>operator&lt;</STRONG> in terms of their contained
subobjects' <STRONG>operator&lt;</STRONG>.</EM></P>
<P><EM>The rest of the comparison operators are omitted by design.]</EM></P>
<h3><a name="free-swap">swap</a></h3>
<pre>template&lt;class T&gt;
void swap(shared_ptr&lt;T&gt; &amp; a, shared_ptr&lt;T&gt; &amp; b); // never throws</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>a.swap(b)</code>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
generic programming.</P>
</BLOCKQUOTE>
<P><EM>[<STRONG>swap</STRONG> is defined in the same namespace as <STRONG>shared_ptr</STRONG>
as this is currently the only legal way to supply a <STRONG>swap</STRONG> function
that has a chance to be used by the standard library.]</EM></P>
<h3><a name="get_pointer">get_pointer</a></h3>
<pre>template&lt;class T&gt;
T * get_pointer(shared_ptr&lt;T&gt; const &amp; p); // never throws</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>p.get()</code>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> Provided as an aid to generic programming. Used by <A href="../bind/mem_fn.html">
mem_fn</A>.</P>
</BLOCKQUOTE>
<h3><a name="static_pointer_cast">static_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; static_pointer_cast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<P><STRONG>Requires:</STRONG> The expression <code>static_cast&lt;T*&gt;(r.get())</code>
must be well-formed.</P>
<P><B>Returns:</B> If <b>r</b> is <i>empty</i>, an <i>empty</i> <b>shared_ptr&lt;T&gt;</b>;
otherwise, a <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy of <code>
static_cast&lt;T*&gt;(r.get())</code> and <i>shares ownership</i> with <b>r</b>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> the seemingly equivalent expression</P>
<p><code>shared_ptr&lt;T&gt;(static_cast&lt;T*&gt;(r.get()))</code></p>
<p>will eventually result in undefined behavior, attempting to delete the same
object twice.</p>
</BLOCKQUOTE>
<h3><a name="const_pointer_cast">const_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; const_pointer_cast(shared_ptr&lt;U&gt; const &amp; r); // never throws</pre>
<BLOCKQUOTE>
<P><STRONG>Requires:</STRONG> The expression <code>const_cast&lt;T*&gt;(r.get())</code>
must be well-formed.</P>
<P><B>Returns:</B> If <b>r</b> is <i>empty</i>, an <i>empty</i> <b>shared_ptr&lt;T&gt;</b>;
otherwise, a <STRONG>shared_ptr&lt;T&gt;</STRONG> object that stores a copy of <code>
const_cast&lt;T*&gt;(r.get())</code> and <i>shares ownership</i> with <b>r</b>.</P>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> the seemingly equivalent expression</P>
<p><code>shared_ptr&lt;T&gt;(const_cast&lt;T*&gt;(r.get()))</code></p>
<p>will eventually result in undefined behavior, attempting to delete the same
object twice.</p>
</BLOCKQUOTE>
<h3><a name="dynamic_pointer_cast">dynamic_pointer_cast</a></h3>
<pre>template&lt;class T, class U&gt;
shared_ptr&lt;T&gt; dynamic_pointer_cast(shared_ptr&lt;U&gt; const &amp; r);</pre>
<BLOCKQUOTE>
<P><STRONG>Requires:</STRONG> The expression <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE>
must be well-formed and its behavior defined.</P>
<P><B>Returns:</B></P>
<UL>
<LI>
When <CODE>dynamic_cast&lt;T*&gt;(r.get())</CODE> returns a nonzero value, a <STRONG>
shared_ptr&lt;T&gt;</STRONG> object that stores a copy of it and <i>shares
ownership</i> with <STRONG>r</STRONG>;
<LI>
Otherwise, an <i>empty</i> <STRONG>shared_ptr&lt;T&gt;</STRONG> object.</LI></UL>
<P><B>Throws:</B> nothing.</P>
<P><B>Notes:</B> the seemingly equivalent expression</P>
<P><CODE>shared_ptr&lt;T&gt;(dynamic_cast&lt;T*&gt;(r.get()))</CODE></P>
<P>will eventually result in undefined behavior, attempting to delete the same
object twice.</P>
</BLOCKQUOTE>
<h3><a name="insertion-operator">operator&lt;&lt;</a></h3>
<pre>template&lt;class E, class T, class Y&gt;
std::basic_ostream&lt;E, T&gt; &amp; operator&lt;&lt; (std::basic_ostream&lt;E, T&gt; &amp; os, shared_ptr&lt;Y&gt; const &amp; p);</pre>
<BLOCKQUOTE>
<p><STRONG>Effects:</STRONG> <code>os &lt;&lt; p.get();</code>.</p>
<P><B>Returns:</B> <b>os</b>.</P>
</BLOCKQUOTE>
<h3><a name="get_deleter">get_deleter</a></h3>
<pre>template&lt;class D, class T&gt;
D * get_deleter(shared_ptr&lt;T&gt; const &amp; p);</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> If <STRONG>*this</STRONG> <EM>owns</EM> a deleter <STRONG>d</STRONG>
of type (cv-unqualified) <STRONG>D</STRONG>, returns <code>&amp;d</code>;
otherwise returns 0.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h2><a name="example">Example</a></h2>
<p>See <A href="example/shared_ptr_example.cpp">shared_ptr_example.cpp</A> for a
complete example program. The program builds a <b>std::vector</b> and <b>std::set</b>
of <b>shared_ptr</b> objects.</p>
<p>Note that after the containers have been populated, some of the <b>shared_ptr</b>
objects will have a use count of 1 rather than a use count of 2, since the set
is a <b>std::set</b> rather than a <b>std::multiset</b>, and thus does not
contain duplicate entries. Furthermore, the use count may be even higher at
various times while <b>push_back</b> and <b>insert</b> container operations are
performed. More complicated yet, the container operations may throw exceptions
under a variety of circumstances. Getting the memory management and exception
handling in this example right without a smart pointer would be a nightmare.</p>
<h2><a name="Handle/Body">Handle/Body</a> Idiom</h2>
<p>One common usage of <b>shared_ptr</b> is to implement a handle/body (also called
pimpl) idiom which avoids exposing the body (implementation) in the header
file.</p>
<p>The <A href="example/shared_ptr_example2_test.cpp">shared_ptr_example2_test.cpp</A>
sample program includes a header file, <A href="example/shared_ptr_example2.hpp">shared_ptr_example2.hpp</A>,
which uses a <b>shared_ptr&lt;&gt;</b> to an incomplete type to hide the
implementation. The instantiation of member functions which require a complete
type occurs in the <A href="example/shared_ptr_example2.cpp">shared_ptr_example2.cpp</A>
implementation file. Note that there is no need for an explicit destructor.
Unlike ~scoped_ptr, ~shared_ptr does not require that <b>T</b> be a complete
type.</p>
<h2><a name="ThreadSafety">Thread Safety</a></h2>
<p><STRONG>shared_ptr</STRONG> objects offer the same level of thread safety as
built-in types. A <STRONG>shared_ptr</STRONG> instance can be "read" (accessed
using only const operations) simultaneously by multiple threads. Different <STRONG>shared_ptr</STRONG>
instances can be "written to" (accessed using mutable operations such as <STRONG>operator=
</STRONG>or <STRONG>reset</STRONG>) simultaneosly by multiple threads (even
when these instances are copies, and share the same reference count
underneath.)</p>
<P>Any other simultaneous accesses result in undefined behavior.</P>
<P>Examples:</P>
<pre>shared_ptr&lt;int&gt; p(new int(42));
//--- Example 1 ---
// thread A
shared_ptr&lt;int&gt; p2(p); // reads p
// thread B
shared_ptr&lt;int&gt; p3(p); // OK, multiple reads are safe
//--- Example 2 ---
// thread A
p.reset(new int(1912)); // writes p
// thread B
p2.reset(); // OK, writes p2
//--- Example 3 ---
// thread A
p = p3; // reads p3, writes p
// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write
//--- Example 4 ---
// thread A
p3 = p2; // reads p2, writes p3
// thread B
// p2 goes out of scope: undefined, the destructor is considered a "write access"
//--- Example 5 ---
// thread A
p3.reset(new int(1));
// thread B
p3.reset(new int(2)); // undefined, multiple writes
</pre>
<p>&nbsp;</p>
<P>Starting with Boost release 1.33.0, <STRONG>shared_ptr</STRONG> uses a lock-free
implementation on the following platforms:</P>
<UL>
<LI>
GNU GCC on x86 or x86-64;
<LI>
GNU GCC on IA64;
<LI>
Metrowerks CodeWarrior on PowerPC;
<LI>
GNU GCC on PowerPC;
<LI>
Windows.</LI></UL>
<P>If your program is single-threaded and does not link to any libraries that might
have used <STRONG>shared_ptr</STRONG> in its default configuration, you can <STRONG>
#define</STRONG> the macro <STRONG>BOOST_SP_DISABLE_THREADS</STRONG> on a
project-wide basis to switch to ordinary non-atomic reference count updates.</P>
<P>(Defining <STRONG>BOOST_SP_DISABLE_THREADS</STRONG> in some, but not all,
translation units is technically a violation of the One Definition Rule and
undefined behavior. Nevertheless, the implementation attempts to do its best to
accommodate the request to use non-atomic updates in those translation units.
No guarantees, though.)</P>
<P>You can define the macro <STRONG>BOOST_SP_USE_PTHREADS</STRONG> to turn off the
lock-free platform-specific implementation and fall back to the generic <STRONG>pthread_mutex_t</STRONG>-based
code.</P>
<h2><a name="FAQ">Frequently Asked Questions</a></h2>
<P><B>Q.</B> There are several variations of shared pointers, with different
tradeoffs; why does the smart pointer library supply only a single
implementation? It would be useful to be able to experiment with each type so
as to find the most suitable for the job at hand?</P>
<P>
<b>A.</b> An important goal of <STRONG>shared_ptr</STRONG> is to provide a
standard shared-ownership pointer. Having a single pointer type is important
for stable library interfaces, since different shared pointers typically cannot
interoperate, i.e. a reference counted pointer (used by library A) cannot share
ownership with a linked pointer (used by library B.)<BR>
</P>
<P><B>Q.</B> Why doesn't <B>shared_ptr</B> have template parameters supplying
traits or policies to allow extensive user customization?</P>
<P>
<B>A.</B> Parameterization discourages users. The <B>shared_ptr</B> template is
carefully crafted to meet common needs without extensive parameterization. Some
day a highly configurable smart pointer may be invented that is also very easy
to use and very hard to misuse. Until then, <B>shared_ptr</B> is the smart
pointer of choice for a wide range of applications. (Those interested in policy
based smart pointers should read <A href="http://www.awprofessional.com/bookstore/product.asp?isbn=0201704315&amp;rl=1">
Modern C++ Design</A> by Andrei Alexandrescu.)<BR>
</P>
<P><B>Q.</B> I am not convinced. Default parameters can be used where appropriate
to hide the complexity. Again, why not policies?</P>
<P>
<B>A.</B> Template parameters affect the type. See the answer to the first
question above.<BR>
</P>
<P><B>Q.</B> Why doesn't <b>shared_ptr</b> use a linked list implementation?</P>
<P>
<b>A.</b> A linked list implementation does not offer enough advantages to
offset the added cost of an extra pointer. See <A href="smarttests.htm">timings</A>
page. In addition, it is expensive to make a linked list implementation thread
safe.<BR>
</P>
<P><b>Q.</b> Why doesn't <b>shared_ptr</b> (or any of the other Boost smart
pointers) supply an automatic conversion to <b>T*</b>?</P>
<P>
<b>A.</b> Automatic conversion is believed to be too error prone.<BR>
</P>
<P><B>Q.</B> Why does <b>shared_ptr</b> supply use_count()?</P>
<P>
<b>A.</b> As an aid to writing test cases and debugging displays. One of the
progenitors had use_count(), and it was useful in tracking down bugs in a
complex project that turned out to have cyclic-dependencies.<BR>
</P>
<P><B>Q.</B> Why doesn't <b>shared_ptr</b> specify complexity requirements?</P>
<P>
<b>A.</b> Because complexity requirements limit implementors and complicate the
specification without apparent benefit to <b>shared_ptr</b> users. For example,
error-checking implementations might become non-conforming if they had to meet
stringent complexity requirements.<BR>
</P>
<P><b>Q.</b> Why doesn't <b>shared_ptr</b> provide a release() function?</P>
<P>
<b>A.</b> <b>shared_ptr</b> cannot give away ownership unless it's unique()
because the other copy will still destroy the object.</P>
<p>Consider:</p>
<blockquote><pre>shared_ptr&lt;int&gt; a(new int);
shared_ptr&lt;int&gt; b(a); // a.use_count() == b.use_count() == 2
int * p = a.release();
// Who owns p now? b will still call delete on it in its destructor.</pre>
</blockquote>
<p>Furthermore, the pointer returned by <code>release()</code> would be difficult
to deallocate reliably, as the source <b>shared_ptr</b> could have been created
with a custom deleter.<BR>
</p>
<P><b>Q.</b> Why is <code>operator-&gt;()</code> const, but its return value is a
non-const pointer to the element type?</P>
<P>
<b>A.</b> Shallow copy pointers, including raw pointers, typically don't
propagate constness. It makes little sense for them to do so, as you can always
obtain a non-const pointer from a const one and then proceed to modify the
object through it.<b>shared_ptr</b> is "as close to raw pointers as possible
but no closer".<BR>
<BR>
</P>
<hr>
<p>
$Date$</p>
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Copyright 2002-2005 Peter Dimov. Distributed under the Boost Software License,
Version 1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A>
or copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

196
smart_ptr.htm Normal file
View File

@@ -0,0 +1,196 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Smart Pointers</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#ffffff" text="#000000">
<h1><A href="../../index.htm"><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" width="277" height="86"
border="0"></A>Smart Pointers</h1>
<p><a href="#Introduction">Introduction</a><br>
<a href="#common_requirements">Common Requirements</a><br>
<a href="#Exception_Safety">Exception Safety</a><br>
<a href="#Exception-specifications">Exception-specifications</a><br>
<a href="#History">History and Acknowledgements</a><br>
<a href="#References">References</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>Smart pointers are objects which store pointers to dynamically allocated (heap)
objects. They behave much like built-in C++ pointers except that they
automatically delete the object pointed to at the appropriate time. Smart
pointers are particularly useful in the face of exceptions as they ensure
proper destruction of dynamically allocated objects. They can also be used to
keep track of dynamically allocated objects shared by multiple owners.</p>
<p>Conceptually, smart pointers are seen as owning the object pointed to, and thus
responsible for deletion of the object when it is no longer needed.</p>
<p>The smart pointer library provides six smart pointer class templates:</p>
<div align="left">
<table border="1" cellpadding="4" cellspacing="0">
<tr>
<td><a href="scoped_ptr.htm"><b>scoped_ptr</b></a></td>
<td><a href="../../boost/scoped_ptr.hpp">&lt;boost/scoped_ptr.hpp&gt;</a></td>
<td>Simple sole ownership of single objects. Noncopyable.</td>
</tr>
<tr>
<td><a href="scoped_array.htm"><b>scoped_array</b></a></td>
<td><a href="../../boost/scoped_array.hpp">&lt;boost/scoped_array.hpp&gt;</a></td>
<td>Simple sole ownership of arrays. Noncopyable.</td>
</tr>
<tr>
<td><a href="shared_ptr.htm"><b>shared_ptr</b></a></td>
<td><a href="../../boost/shared_ptr.hpp">&lt;boost/shared_ptr.hpp&gt;</a></td>
<td>Object ownership shared among multiple pointers.</td>
</tr>
<tr>
<td><a href="shared_array.htm"><b>shared_array</b></a></td>
<td><a href="../../boost/shared_array.hpp">&lt;boost/shared_array.hpp&gt;</a></td>
<td>Array ownership shared among multiple pointers.</td>
</tr>
<tr>
<td><a href="weak_ptr.htm"><b>weak_ptr</b></a></td>
<td><a href="../../boost/weak_ptr.hpp">&lt;boost/weak_ptr.hpp&gt;</a></td>
<td>Non-owning observers of an object owned by <b>shared_ptr</b>.</td>
</tr>
<tr>
<td><a href="intrusive_ptr.html"><b>intrusive_ptr</b></a></td>
<td><a href="../../boost/intrusive_ptr.hpp">&lt;boost/intrusive_ptr.hpp&gt;</a></td>
<td>Shared ownership of objects with an embedded reference count.</td>
</tr>
</table>
</div>
<p>These templates are designed to complement the <b>std::auto_ptr</b> template.</p>
<p>They are examples of the "resource acquisition is initialization" idiom
described in Bjarne Stroustrup's "The C++ Programming Language", 3rd edition,
Section 14.4, Resource Management.</p>
<p>Additionally, the smart pointer library provides efficient factory functions
for creating <code>shared_ptr</code> objects:</p>
<div align="left">
<table border="1" cellpadding="4" cellspacing="0">
<tr>
<td><a href="make_shared.html"><b>make_shared and allocate_shared</b></a></td>
<td><a href="../../boost/make_shared.hpp">&lt;boost/make_shared.hpp&gt;</a></td>
<td>Efficient creation of <code>shared_ptr</code> objects.</td>
</tr>
</table>
</div>
<p>A test program, <a href="test/smart_ptr_test.cpp">smart_ptr_test.cpp</a>, is
provided to verify correct operation.</p>
<p>A page on <a href="compatibility.htm">compatibility</a> with older versions of
the Boost smart pointer library describes some of the changes since earlier
versions of the smart pointer implementation.</p>
<p>A page on <a href="smarttests.htm">smart pointer timings</a> will be of interest
to those curious about performance issues.</p>
<P>A page on <A href="sp_techniques.html">smart pointer programming techniques</A> lists
some advanced applications of <code>shared_ptr</code> and <code>weak_ptr</code>.</P>
<h2><a name="common_requirements">Common Requirements</a></h2>
<p>These smart pointer class templates have a template parameter, <b>T</b>, which
specifies the type of the object pointed to by the smart pointer. The behavior
of the smart pointer templates is undefined if the destructor or <b>operator delete</b>
for objects of type <b>T</b> throw exceptions.</p>
<p><b>T</b> may be an incomplete type at the point of smart pointer declaration.
Unless otherwise specified, it is required that <b>T</b> be a complete type at
points of smart pointer instantiation. Implementations are required to diagnose
(treat as an error) all violations of this requirement, including deletion of
an incomplete type. See the description of the <a href="../utility/utility.htm#checked_delete">
<b>checked_delete</b></a> function template.</p>
<P>Note that <STRONG>shared_ptr</STRONG> does not have this restriction, as most of
its member functions do not require <STRONG>T</STRONG> to be a complete type.</P>
<h3>Rationale</h3>
<p>The requirements on <b>T</b> are carefully crafted to maximize safety yet allow
handle-body (also called pimpl) and similar idioms. In these idioms a smart
pointer may appear in translation units where <b>T</b> is an incomplete type.
This separates interface from implementation and hides implementation from
translation units which merely use the interface. Examples described in the
documentation for specific smart pointers illustrate use of smart pointers in
these idioms.</p>
<p>Note that <b>scoped_ptr</b> requires that <b>T</b> be a complete type at
destruction time, but <b>shared_ptr</b> does not.</p>
<h2><a name="Exception_Safety">Exception Safety</a></h2>
<p>Several functions in these smart pointer classes are specified as having "no
effect" or "no effect except such-and-such" if an exception is thrown. This
means that when an exception is thrown by an object of one of these classes,
the entire program state remains the same as it was prior to the function call
which resulted in the exception being thrown. This amounts to a guarantee that
there are no detectable side effects. Other functions never throw exceptions.
The only exception ever thrown by functions which do throw (assuming <b>T</b> meets
the <a href="#common_requirements">common requirements</a>) is <b>std::bad_alloc</b>,
and that is thrown only by functions which are explicitly documented as
possibly throwing <b>std::bad_alloc</b>.</p>
<h2><a name="Exception-specifications">Exception-specifications</a></h2>
<p>Exception-specifications are not used; see <a href="http://www.boost.org/more/lib_guide.htm#Exception-specification">
exception-specification rationale</a>.</p>
<p>All the smart pointer templates contain member functions which can never throw
exceptions, because they neither throw exceptions themselves nor call other
functions which may throw exceptions. These members are indicated by a comment: <code>
// never throws</code>.
</p>
<p>Functions which destroy objects of the pointed to type are prohibited from
throwing exceptions by the <a href="#common_requirements">common requirements</a>.</p>
<h2><a name="History">History</a> and Acknowledgements</h2>
<p>January 2002. Peter Dimov reworked all four classes, adding features, fixing
bugs, and splitting them into four separate headers, and added <b>weak_ptr</b>.
See the <a href="compatibility.htm">compatibility</a> page for a summary of the
changes.</p>
<p>May 2001. Vladimir Prus suggested requiring a complete type on destruction.
Refinement evolved in discussions including Dave Abrahams, Greg Colvin, Beman
Dawes, Rainer Deyke, Peter Dimov, John Maddock, Vladimir Prus, Shankar Sai, and
others.</p>
<p>November 1999. Darin Adler provided <b>operator ==</b>, <b>operator !=</b>, and <b>std::swap</b>
and <b>std::less</b> specializations for shared types.</p>
<p>September 1999. Luis Coelho provided <b>shared_ptr::swap</b> and <b>shared_array::swap</b></p>
<p>May 1999. In April and May, 1999, Valentin Bonnard and David Abrahams made a
number of suggestions resulting in numerous improvements.</p>
<p>October 1998. Beman Dawes proposed reviving the original semantics under the
names <b>safe_ptr</b> and <b>counted_ptr</b>, meeting of Per Andersson, Matt
Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis, Dietmar K&uuml;hl,
Nathan Myers, Chichiang Wan and Judy Ward. During the discussion, the four new
class names were finalized, it was decided that there was no need to exactly
follow the <b>std::auto_ptr</b> interface, and various function signatures and
semantics were finalized.</p>
<p>Over the next three months, several implementations were considered for <b>shared_ptr</b>,
and discussed on the <a href="http://www.boost.org">boost.org</a> mailing list.
The implementation questions revolved around the reference count which must be
kept, either attached to the pointed to object, or detached elsewhere. Each of
those variants have themselves two major variants:
<ul>
<li>
Direct detached: the shared_ptr contains a pointer to the object, and a pointer
to the count.
<li>
Indirect detached: the shared_ptr contains a pointer to a helper object, which
in turn contains a pointer to the object and the count.
<li>
Embedded attached: the count is a member of the object pointed to.
<li>
Placement attached: the count is attached via operator new manipulations.</li>
</ul>
<p>Each implementation technique has advantages and disadvantages. We went so far
as to run various timings of the direct and indirect approaches, and found that
at least on Intel Pentium chips there was very little measurable difference.
Kevlin Henney provided a paper he wrote on "Counted Body Techniques." Dietmar
K&uuml;hl suggested an elegant partial template specialization technique to allow
users to choose which implementation they preferred, and that was also
experimented with.</p>
<p>But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage
users", and in the end we choose to supply only the direct implementation.</p>
<p>Summer, 1994. Greg Colvin proposed to the C++ Standards Committee classes named <b>auto_ptr</b>
and <b>counted_ptr</b> which were very similar to what we now call <b>scoped_ptr</b>
and <b>shared_ptr</b>. <a href="#Col-94">[Col-94]</a> In one of the very few
cases where the Library Working Group's recommendations were not followed by
the full committee, <b>counted_ptr</b> was rejected and surprising
transfer-of-ownership semantics were added to <b>auto_ptr</b>.</p>
<h2><a name="References">References</a></h2>
<p>[<a name="Col-94">Col-94</a>] Gregory Colvin, <a href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf">
Exception Safe Smart Pointers</a>, C++ committee document 94-168/N0555,
July, 1994.</p>
<p>[<a name="E&amp;D-94">E&amp;D-94</a>] John R. Ellis &amp; David L. Detlefs, <a href="http://www.usenix.org/publications/library/proceedings/c++94/full_papers/ellis.a">
Safe, Efficient Garbage Collection for C++</a>, Usenix Proceedings,
February, 1994. This paper includes an extensive discussion of weak pointers
and an extensive bibliography.</p>
<hr>
<p>$Date$</p>
<p><small>Copyright 1999 Greg Colvin and Beman Dawes. Copyright 2002 Darin Adler.
Distributed under the Boost Software License, Version 1.0. See accompanying
file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or copy at
<A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

BIN
smarttest.zip Normal file

Binary file not shown.

543
smarttests.htm Normal file
View File

@@ -0,0 +1,543 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Smart Pointer Timings</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="#FFFFFF">
<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle" WIDTH="277" HEIGHT="86">Smart Pointer Timings</h1>
<p>In late January 2000, Mark Borgerding put forward a suggestion to boost for
a new design of smart pointer whereby an intrusive doubly linked list is used
to join together all instances of smart pointers sharing a given raw pointer.
This allowed avoidance of the costly heap allocation of a reference count that
occurred in the initial construction of the then current version of boost::shared_ptr.
Of course, nothing is for free and the benefit here was gained at the expense
of increased size and more costly copy operations. A debate ensued on the boost
mailing list and the tests which this page describes were performed to provide
a guide for current and future investigations into smart pointer implementation
strategies.</p>
<p>Thanks are due to <a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>,
Gavin Collings,
<a href="http://www.boost.org/people/greg_colvin.htm">Greg Colvin</a> and
<a href="http://www.boost.org/people/beman_dawes.html">Beman Dawes</a>
for test code and trial implementations, the final version of which can be found
in .zip format <a href="smarttest.zip">here</a>.</p>
<h2>Description</h2>
<p>Two tests were run: the first aimed to obtain timings for two basic individual
operations:</p>
<ol type="i">
<li> Initial construction from raw pointer.</li>
<li> An amortized copy operation consisting of half an assignment and half a
copy construction - designed to reflect average usage.</li>
</ol>
<p>The second attempted to gain more insight into normal usage by timing the fill
and sort algorithms for vectors and lists filled with the various smart pointers.</p>
<p>Five smart pointer implementation strategies were tested:</p>
<ol type="i">
<li>Counted pointer using a heap allocated reference count, this is referred
to as <b>simple counted</b>.</li>
<li>Counted pointer using a special purpose allocator for the reference count
- <b>special counted</b>.</li>
<li>Counted pointer using an intrusive reference count - <b>intrusive</b>.</li>
<li>Linked pointer as described above - <b>linked</b>.</li>
<li>Cyclic pointer, a counted implementation using a std::deque for allocation
with provision for weak pointers and garbage collection of cycles of pointers
- <b>cyclic</b>.</li>
</ol>
<p>on two compilers:</p>
<ol type="i">
<li>MSVC 6.0 service pack 3, using default release optimization mode (/O2 -
optimized for speed, no inlining of functions defined outside a class body
unless specified as inline).</li>
<li>gcc 2.95.2 using full optimization (-O3 -DNDEBUG).</li>
</ol>
<p>Additionally, generated pointer sizes (taking into account struct alignment)
were compared, as were generated code sizes for MSVC mainly by manual inspection
of generated assembly code - a necessity due to function inlining.</p>
<p>All tests were run on a PII-200 running Windows NT version 4.0</p>
<h2>&nbsp;</h2>
<h2>Operation Timing Test Results</h2>
<p>The following graphs show the overall time in nanoseconds to acquire a pointer
(default construction) perform n amortized copy operations on it and finally
release it. The initial allocation time for the contained pointer is not included,
although the time for it's deallocation is. The contained pointer pointed to
a trivial class, but for the inclusion of an intrusive reference count for the
benefit of the intrusive counted shared pointer. A dumb pointer (i.e. a smart
pointer that simply acquires and releases its contained pointer with no extra
overhead) and a raw pointer were also included for comparison.</p>
<table border="0" align="center">
<tr>
<td width="20" height="20">&nbsp;</td>
<td>&nbsp;</td>
<td width="20">&nbsp;</td>
</tr>
<tr>
<td width="20">&nbsp; </td>
<td><img src="msvcspeed.gif" width="560" height="355" alt="MSVC speed graph"></td>
<td width="20">&nbsp;</td>
</tr>
<tr>
<td height="20">&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>&nbsp;</td>
<td><img src="gccspeed.gif" width="560" height="355" alt="GCC speed graph"></td>
<td>&nbsp;</td>
</tr>
<tr>
<td height="20">&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
</tr>
</table>
<p>&nbsp;</p>
<p>Fitting straight lines to the above plots gives the following figures for initialization
and amortized copy operation for the two compilers (times in nanoseconds, errors
at two standard deviations) : -</p>
<p>&nbsp;</p>
<h4 align="center">MSVC</h4>
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="400">
<tr>
<th width="120">
<div align="right"></div>
</th>
<th class="codetabletop" width="120">
<div align="center">initialization</div>
</th>
<th class="codetabletop" width="120">copy operation</th>
</tr>
<tr>
<th class="codetableleft">
<div align="right">simple counted</div>
</th>
<td class="codetablecell" align="center">3000 +/- 170</td>
<td class="codetablecell" align="center">104 +/- 31</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">special counted</div>
</th>
<td class="codetablecell" align="center">1330 +/- 50</td>
<td class="codetablecell" align="center">85 +/- 9</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">intrusive</div>
</th>
<td class="codetablecell" align="center">1000 +/- 20</td>
<td class="codetablecell" align="center">71 +/- 3</td>
</tr>
<tr>
<th class="codetableleft" align="right">linked</th>
<td class="codetablecell" align="center">970 +/- 60</td>
<td class="codetablecell" align="center">136 +/- 10</td>
</tr>
<tr>
<th class="codetableleft" align="right">cyclic</th>
<td class="codetablecell" align="center">1290 +/- 70</td>
<td class="codetablecell" align="center">112 +/- 12</td>
</tr>
<tr>
<th class="codetableleft" align="right">dumb</th>
<td class="codetablecell" align="center">1020 +/- 20</td>
<td class="codetablecell" align="center">10 +/- 4</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">raw</div>
</th>
<td class="codetablecell" align="center">1038 +/- 30</td>
<td class="codetablecell" align="center">10 +/- 5</td>
</tr>
</table>
<h4 align="center">&nbsp;</h4>
<h4 align="center">GCC</h4>
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="400">
<tr>
<th width="120">
<div align="right"></div>
</th>
<th class="codetabletop" width="120">
<div align="center">initialization</div>
</th>
<th class="codetabletop" width="120">copy operation</th>
</tr>
<tr>
<th class="codetableleft">
<div align="right">simple counted</div>
</th>
<td class="codetablecell" align="center">4620 +/- 150</td>
<td class="codetablecell" align="center">301 +/- 28</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">special counted</div>
</th>
<td class="codetablecell" align="center">1990 +/- 40</td>
<td class="codetablecell" align="center">264 +/- 7</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">intrusive</div>
</th>
<td class="codetablecell" align="center">1590 +/- 70</td>
<td class="codetablecell" align="center">181 +/- 12</td>
</tr>
<tr>
<th class="codetableleft" align="right">linked</th>
<td class="codetablecell" align="center">1470 +/- 140</td>
<td class="codetablecell" align="center">345 +/- 26</td>
</tr>
<tr>
<th class="codetableleft" align="right">cyclic</th>
<td class="codetablecell" align="center">2180 +/- 100</td>
<td class="codetablecell" align="center">330 +/- 18</td>
</tr>
<tr>
<th class="codetableleft" align="right">dumb</th>
<td class="codetablecell" align="center">1590 +/- 70</td>
<td class="codetablecell" align="center">74 +/- 12</td>
</tr>
<tr>
<th class="codetableleft" align="right">
<div align="right">raw</div>
</th>
<td class="codetablecell" align="center">1430 +/- 60</td>
<td class="codetablecell" align="center">27 +/- 11</td>
</tr>
</table>
<p>Note that the above times include a certain amount of loop overhead etc. for
each operation. An estimate of the pure smart pointer operation time 'overhead'
can be obtained by subtracting the dumb or raw figure from the smart pointer
time of interest.</p>
<h3>Detail</h3>
<p>The test involved iterating a loop which creates raw pointers. These were then
shared among a varying number (set size) of smart pointers. A range of set sizes
was used and then a line fitted to get a linear relation with number of initializations
and copy-operations. A spreadsheet was used for the line fit, and to produce
the performance graphs above.</p>
<h2>&nbsp;</h2>
<h2>Container Test Results</h2>
<p>To gain some insight in to operation within real life programs, this test was
devised. Smart pointers were used to fill standard containers which were then
sorted.</p>
<p>In this case, the contained pointer pointed to a class which initializes a
private data member to a random value in its default constructor. This value
is used subsequently for the sort comparison test. The class also contains an
intrusive reference count for the benefit of the intrusive counted pointer.</p>
<p> All times are in seconds for 300,000 contained pointers.</p>
<h4 align="center">GCC</h4>
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="500">
<tr>
<th>&nbsp;</th>
<th class="codetabletop" colspan="2">vector</th>
<th class="codetabletop" colspan="2">list</th>
</tr>
<tr>
<th width="120">
<div align="right"></div>
</th>
<th class="codetabletop2" width="80">
<div align="center">fill</div>
</th>
<th class="codetabletop2" width="80">sort</th>
<th class="codetabletop2" width="80">fill</th>
<th class="codetabletop2" width="80">sort</th>
</tr>
<tr>
<th class="codetableleft">
<div align="right">simple counted</div>
</th>
<td class="codetablecell" align="center">46.54</td>
<td class="codetablecell" align="center">2.44</td>
<td class="codetablecell" align="center">47.09</td>
<td class="codetablecell" align="center">3.22</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">special counted</div>
</th>
<td class="codetablecell" align="center">14.02</td>
<td class="codetablecell" align="center">2.83</td>
<td class="codetablecell" align="center">7.28</td>
<td class="codetablecell" align="center">3.21</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">intrusive</div>
</th>
<td class="codetablecell" align="center">12.15</td>
<td class="codetablecell" align="center">1.91</td>
<td class="codetablecell" align="center">7.99</td>
<td class="codetablecell" align="center">3.08</td>
</tr>
<tr>
<th class="codetableleft" align="right">linked</th>
<td class="codetablecell" align="center">12.46</td>
<td class="codetablecell" align="center">2.32</td>
<td class="codetablecell" align="center">8.14</td>
<td class="codetablecell" align="center">3.27</td>
</tr>
<tr>
<th class="codetableleft" align="right">cyclic</th>
<td class="codetablecell" align="center">22.60</td>
<td class="codetablecell" align="center">3.19</td>
<td class="codetablecell" align="center">1.63</td>
<td class="codetablecell" align="center">3.18</td>
</tr>
<tr>
<th class="codetableleft" align="right">
<div align="right">raw</div>
</th>
<td class="codetablecell" align="center">11.81</td>
<td class="codetablecell" align="center">0.24</td>
<td class="codetablecell" align="center">27.51</td>
<td class="codetablecell" align="center">0.77</td>
</tr>
</table>
<p>&nbsp;</p>
<h4 align="center">MSVC</h4>
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="500">
<tr>
<th>&nbsp;</th>
<th class="codetabletop" colspan="2">vector</th>
<th class="codetabletop" colspan="2">list</th>
</tr>
<tr>
<th width="120">
<div align="right"></div>
</th>
<th class="codetabletop2" width="80">
<div align="center">fill</div>
</th>
<th class="codetabletop2" width="80">sort</th>
<th class="codetabletop2" width="80">fill</th>
<th class="codetabletop2" width="80">sort</th>
</tr>
<tr>
<th class="codetableleft">
<div align="right">simple counted</div>
</th>
<td class="codetablecell" align="center">1.83</td>
<td class="codetablecell" align="center">2.37</td>
<td class="codetablecell" align="center">1.86</td>
<td class="codetablecell" align="center">4.85</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">special counted</div>
</th>
<td class="codetablecell" align="center">1.04</td>
<td class="codetablecell" align="center">2.35</td>
<td class="codetablecell" align="center">1.38</td>
<td class="codetablecell" align="center">4.58</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">intrusive</div>
</th>
<td class="codetablecell" align="center">1.04</td>
<td class="codetablecell" align="center">1.84</td>
<td class="codetablecell" align="center">1.16</td>
<td class="codetablecell" align="center">4.29</td>
</tr>
<tr>
<th class="codetableleft" align="right">linked</th>
<td class="codetablecell" align="center">1.08</td>
<td class="codetablecell" align="center">2.00</td>
<td class="codetablecell" align="center">1.21</td>
<td class="codetablecell" align="center">4.33</td>
</tr>
<tr>
<th class="codetableleft" align="right">cyclic</th>
<td class="codetablecell" align="center">1.38</td>
<td class="codetablecell" align="center">2.84</td>
<td class="codetablecell" align="center">1.47</td>
<td class="codetablecell" align="center">4.73</td>
</tr>
<tr>
<th class="codetableleft" align="right">
<div align="right">raw</div>
</th>
<td class="codetablecell" align="center">0.67</td>
<td class="codetablecell" align="center">0.28</td>
<td class="codetablecell" align="center">1.24</td>
<td class="codetablecell" align="center">1.81</td>
</tr>
</table>
<p>&nbsp;</p>
<h2>Code Size</h2>
<p>The following code sizes were determined by inspection of generated code for
MSVC only. Sizes are given in the form N / M / I where:</p>
<ul type="circle">
<li> N is the instruction count of the operation</li>
<li>M is the size of the code in bytes</li>
<li>I determines whether generated code was inlined or not I = inline, O = &quot;outline&quot;</li>
</ul>
<p>&nbsp;</p>
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="570">
<tr>
<th height="28" width="140">
<div align="right"></div>
</th>
<th height="28" class="codetabletop" width="80">
<div align="center">ptr()</div>
</th>
<th height="28" class="codetabletop" width="80">ptr(p)</th>
<th height="28" class="codetabletop" width="80">ptr(ptr)</th>
<th height="28" class="codetabletop" width="80">op=()</th>
<th height="28" class="codetabletop" width="80">
<div align="center">~ptr()</div>
</th>
</tr>
<tr>
<th class="codetableleft">
<div align="right">simple counted</div>
</th>
<td class="codetablecell" align="center">38/110/O</td>
<td class="codetablecell" align="center">38/110/O</td>
<td class="codetablecell" align="center">9/23/I</td>
<td class="codetablecell" align="center">22/57/I</td>
<td class="codetablecell" align="center">17/40/I</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">special counted</div>
</th>
<td class="codetablecell" align="center"><font size="-1">50/141/O</font></td>
<td class="codetablecell" align="center"><font size="-1">50/141/O</font></td>
<td class="codetablecell" align="center"><font size="-1">9/23/I</font></td>
<td class="codetablecell" align="center"><font size="-1">23/64/I</font></td>
<td class="codetablecell" align="center"><font size="-1">13/38/I</font></td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">intrusive</div>
</th>
<td class="codetablecell" align="center"><font size="-1">1/2/I</font></td>
<td class="codetablecell" align="center"><font size="-1">3/6/I</font></td>
<td class="codetablecell" align="center"><font size="-1">3/6/I</font></td>
<td class="codetablecell" align="center"><font size="-1">6/11/I</font></td>
<td class="codetablecell" align="center"><font size="-1">6/11/I</font></td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">linked</div>
</th>
<td class="codetablecell" align="center"><font size="-1">5/19/I</font></td>
<td class="codetablecell" align="center"><font size="-1">5/15/I</font></td>
<td class="codetablecell" align="center"><font size="-1">10/30/I</font></td>
<td class="codetablecell" align="center"><font size="-1">27/59/I</font></td>
<td class="codetablecell" align="center"><font size="-1">14/38/I</font></td>
</tr>
</table>
<p>During the code inspection, a couple of minor points were noticed: -</p>
<ul>
<li>Function inlining was critical to performance.</li>
<li>For MSVC, at least, a &quot;delete 0&quot; caused execution of 11 assembly
instructions, including a function call. So in cases where performance is
at an absolute premium it can be worth inserting the extra manual test.</li>
</ul>
<h2>&nbsp;</h2>
<h2>Data Size</h2>
<p>The following smart pointer sizes were obtained in bytes</p>
<table align="center" cellpadding="5" cellspacing="0" class="codetable" width="270">
<tr>
<th height="28" width="150">
<div align="right"></div>
</th>
<th height="28" class="codetabletop" width="60">
<div align="center">MSVC</div>
</th>
<th height="28" class="codetabletop" width="60">
<div align="center">GCC</div>
</th>
</tr>
<tr>
<th class="codetableleft">
<div align="right">simple counted</div>
</th>
<td class="codetablecell">
<div align="center">8</div>
</td>
<td class="codetablecell">
<div align="center">8</div>
</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">special counted</div>
</th>
<td class="codetablecell">
<div align="center">8</div>
</td>
<td class="codetablecell">
<div align="center">12</div>
</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">intrusive</div>
</th>
<td class="codetablecell">
<div align="center">4</div>
</td>
<td class="codetablecell">
<div align="center">4</div>
</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">linked</div>
</th>
<td class="codetablecell">
<div align="center">12</div>
</td>
<td class="codetablecell">
<div align="center">12</div>
</td>
</tr>
<tr>
<th class="codetableleft">
<div align="right">cyclic</div>
</th>
<td class="codetablecell">
<div align="center">8</div>
</td>
<td class="codetablecell">
<div align="center">8</div>
</td>
</tr>
</table>
<h2>&nbsp;</h2>
<h2>Summary</h2>
<p>The timing results mainly speak for themselves: clearly an intrusive pointer
outperforms all others and a simple heap based counted pointer has poor performance
relative to other implementations. The selection of an optimal non-intrusive
smart pointer implementation is more application dependent, however. Where small
numbers of copies are expected, it is likely that the linked implementation
will be favoured. Conversely, for larger numbers of copies a counted pointer
with some type of special purpose allocator looks like a win. Other factors
to bear in mind are: -</p>
<ul>
<li>Deterministic individual, as opposed to amortized, operation time. This
weighs against any implementation depending on an allocator.</li>
<li>Multithreaded synchronization. This weighs against an implementation which
spreads its information as in the case of linked pointer.</li>
</ul>
<hr>
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B %Y" startspan -->19 August 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" -->
</p>
<p><EFBFBD> Copyright Gavin Collings 2000. Permission to copy, use, modify, sell
and distribute this document is granted provided this copyright notice appears in all
copies. This document is provided &quot;as is&quot; without express or implied warranty,
and with no claim as to its suitability for any purpose.</p>
</body>
</html>

765
sp_techniques.html Normal file
View File

@@ -0,0 +1,765 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Smart Pointer Programming Techniques</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body text="#000000" bgColor="#ffffff">
<h1><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" align="middle"
border="0"></A>Smart Pointer Programming Techniques</h1>
<p><A href="#incomplete">Using incomplete classes for implementation hiding</A><br>
<A href="#pimpl">The "Pimpl" idiom</A><br>
<A href="#abstract">Using abstract classes for implementation hiding</A><br>
<A href="#preventing_delete">Preventing <code>delete px.get()</code></A><br>
<A href="#array">Using a <code>shared_ptr</code> to hold a pointer to an array</A><br>
<A href="#encapsulation">Encapsulating allocation details, wrapping factory
functions</A><br>
<A href="#static">Using a <code>shared_ptr</code> to hold a pointer to a statically
allocated object</A><br>
<A href="#com">Using a <code>shared_ptr</code> to hold a pointer to a COM object</A><br>
<A href="#intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object
with an embedded reference count</A><br>
<A href="#another_sp">Using a <code>shared_ptr</code> to hold another shared
ownership smart pointer</A><br>
<A href="#from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A><br>
<A href="#in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>)
to <code>this</code> in a constructor</A><br>
<A href="#from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A><br>
<A href="#handle">Using <code>shared_ptr</code> as a smart counted handle</A><br>
<A href="#on_block_exit">Using <code>shared_ptr</code> to execute code on block
exit</A><br>
<A href="#pvoid">Using <code>shared_ptr&lt;void&gt;</code> to hold an arbitrary
object</A><br>
<A href="#extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code>
instances</A><br>
<A href="#as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A><br>
<A href="#wrapper">Using <code>shared_ptr</code> to wrap member function calls</A><br>
<A href="#delayed">Delayed deallocation</A><br>
<A href="#weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A><br>
</p>
<h2><A name="incomplete">Using incomplete classes for implementation hiding</A></h2>
<p>A proven technique (that works in C, too) for separating interface from
implementation is to use a pointer to an incomplete class as an opaque handle:</p>
<pre>class FILE;
FILE * fopen(char const * name, char const * mode);
void fread(FILE * f, void * data, size_t size);
void fclose(FILE * f);
</pre>
<p>It is possible to express the above interface using <code>shared_ptr</code>,
eliminating the need to manually call <code>fclose</code>:</p>
<pre>class FILE;
shared_ptr&lt;FILE&gt; fopen(char const * name, char const * mode);
void fread(shared_ptr&lt;FILE&gt; f, void * data, size_t size);
</pre>
<p>This technique relies on <code>shared_ptr</code>'s ability to execute a custom
deleter, eliminating the explicit call to <code>fclose</code>, and on the fact
that <code>shared_ptr&lt;X&gt;</code> can be copied and destroyed when <code>X</code>
is incomplete.</p>
<h2><A name="pimpl">The "Pimpl" idiom</A></h2>
<p>A C++ specific variation of the incomplete class pattern is the "Pimpl" idiom.
The incomplete class is not exposed to the user; it is hidden behind a
forwarding facade. <code>shared_ptr</code> can be used to implement a "Pimpl":</p>
<pre>// file.hpp:
class file
{
private:
class impl;
shared_ptr&lt;impl&gt; pimpl_;
public:
file(char const * name, char const * mode);
// compiler generated members are fine and useful
void read(void * data, size_t size);
};
</pre>
<pre>// file.cpp:
#include "file.hpp"
class file::impl
{
private:
impl(impl const &amp;);
impl &amp; operator=(impl const &amp;);
// private data
public:
impl(char const * name, char const * mode) { ... }
~impl() { ... }
void read(void * data, size_t size) { ... }
};
file::file(char const * name, char const * mode): pimpl_(new impl(name, mode))
{
}
void file::read(void * data, size_t size)
{
pimpl_-&gt;read(data, size);
}
</pre>
<p>The key thing to note here is that the compiler-generated copy constructor,
assignment operator, and destructor all have a sensible meaning. As a result, <code>
file</code> is <code>CopyConstructible</code> and <code>Assignable</code>,
allowing its use in standard containers.</p>
<h2><A name="abstract">Using abstract classes for implementation hiding</A></h2>
<p>Another widely used C++ idiom for separating inteface and implementation is to
use abstract base classes and factory functions. The abstract classes are
sometimes called "interfaces" and the pattern is known as "interface-based
programming". Again, <code>shared_ptr</code> can be used as the return type of
the factory functions:</p>
<pre>// X.hpp:
class X
{
public:
virtual void f() = 0;
virtual void g() = 0;
protected:
~X() {}
};
shared_ptr&lt;X&gt; createX();
</pre>
<pre>-- X.cpp:
class X_impl: public X
{
private:
X_impl(X_impl const &amp;);
X_impl &amp; operator=(X_impl const &amp;);
public:
virtual void f()
{
// ...
}
virtual void g()
{
// ...
}
};
shared_ptr&lt;X&gt; createX()
{
shared_ptr&lt;X&gt; px(new X_impl);
return px;
}
</pre>
<p>A key property of shared_ptr is that the allocation, construction, deallocation,
and destruction details are captured at the point of construction, inside the
factory function. Note the protected and nonvirtual destructor in the example
above. The client code cannot, and does not need to, delete a pointer to <code>X</code>;
the <code>shared_ptr&lt;X&gt;</code> instance returned from <code>createX</code>
will correctly call <code>~X_impl</code>.</p>
<h2><A name="preventing_delete">Preventing <code>delete px.get()</code></A></h2>
<p>It is often desirable to prevent client code from deleting a pointer that is
being managed by <code>shared_ptr</code>. The previous technique showed one
possible approach, using a protected destructor. Another alternative is to use
a private deleter:</p>
<pre>class X
{
private:
~X();
class deleter;
friend class deleter;
class deleter
{
public:
void operator()(X * p) { delete p; }
};
public:
static shared_ptr&lt;X&gt; create()
{
shared_ptr&lt;X&gt; px(new X, X::deleter());
return px;
}
};
</pre>
<h2><A name="array">Using a <code>shared_ptr</code> to hold a pointer to an array</A></h2>
<p>A <code>shared_ptr</code> can be used to hold a pointer to an array allocated
with <code>new[]</code>:</p>
<pre>shared_ptr&lt;X&gt; px(new X[1], <A href="../utility/checked_delete.html" >checked_array_deleter</A>&lt;X&gt;());
</pre>
<p>Note, however, that <code><A href="shared_array.htm">shared_array</A></code> is
often preferable, if this is an option. It has an array-specific interface,
without <code>operator*</code> and <code>operator-&gt;</code>, and does not
allow pointer conversions.</p>
<h2><A name="encapsulation">Encapsulating allocation details, wrapping factory
functions</A></h2>
<p><code>shared_ptr</code> can be used in creating C++ wrappers over existing C
style library interfaces that return raw pointers from their factory functions
to encapsulate allocation details. As an example, consider this interface,
where <code>CreateX</code> might allocate <code>X</code> from its own private
heap, <code>~X</code> may be inaccessible, or <code>X</code> may be incomplete:</p>
<pre>X * CreateX();
void DestroyX(X *);
</pre>
<p>The only way to reliably destroy a pointer returned by <code>CreateX</code> is
to call <code>DestroyX</code>.</p>
<P>Here is how a <code>shared_ptr</code>-based wrapper may look like:</P>
<pre>shared_ptr&lt;X&gt; createX()
{
shared_ptr&lt;X&gt; px(CreateX(), DestroyX);
return px;
}
</pre>
<p>Client code that calls <code>createX</code> still does not need to know how the
object has been allocated, but now the destruction is automatic.</p>
<h2><A name="static">Using a <code>shared_ptr</code> to hold a pointer to a statically
allocated object</A></h2>
<p>Sometimes it is desirable to create a <code>shared_ptr</code> to an already
existing object, so that the <code>shared_ptr</code> does not attempt to
destroy the object when there are no more references left. As an example, the
factory function:</p>
<pre>shared_ptr&lt;X&gt; createX();
</pre>
<p>in certain situations may need to return a pointer to a statically allocated <code>X</code>
instance.</p>
<P>The solution is to use a custom deleter that does nothing:</P>
<pre>struct null_deleter
{
void operator()(void const *) const
{
}
};
static X x;
shared_ptr&lt;X&gt; createX()
{
shared_ptr&lt;X&gt; px(&amp;x, null_deleter());
return px;
}
</pre>
<p>The same technique works for any object known to outlive the pointer.</p>
<h2><A name="com">Using a <code>shared_ptr</code> to hold a pointer to a COM Object</A></h2>
<p>Background: COM objects have an embedded reference count and two member
functions that manipulate it. <code>AddRef()</code> increments the count. <code>Release()</code>
decrements the count and destroys itself when the count drops to zero.</p>
<P>It is possible to hold a pointer to a COM object in a <code>shared_ptr</code>:</P>
<pre>shared_ptr&lt;IWhatever&gt; make_shared_from_COM(IWhatever * p)
{
p-&gt;AddRef();
shared_ptr&lt;IWhatever&gt; pw(p, <A href="../bind/mem_fn.html" >mem_fn</A>(&amp;IWhatever::Release));
return pw;
}
</pre>
<p>Note, however, that <code>shared_ptr</code> copies created from <code>pw</code> will
not "register" in the embedded count of the COM object; they will share the
single reference created in <code>make_shared_from_COM</code>. Weak pointers
created from <code>pw</code> will be invalidated when the last <code>shared_ptr</code>
is destroyed, regardless of whether the COM object itself is still alive.</p>
<P>As <A href="../bind/mem_fn.html#Q3">explained</A> in the <code>mem_fn</code> documentation,
you need to <A href="../bind/mem_fn.html#stdcall">#define
BOOST_MEM_FN_ENABLE_STDCALL</A> first.</P>
<h2><A name="intrusive">Using a <code>shared_ptr</code> to hold a pointer to an object
with an embedded reference count</A></h2>
<p>This is a generalization of the above technique. The example assumes that the
object implements the two functions required by <code><A href="intrusive_ptr.html">intrusive_ptr</A></code>,
<code>intrusive_ptr_add_ref</code> and <code>intrusive_ptr_release</code>:</p>
<pre>template&lt;class T&gt; struct intrusive_deleter
{
void operator()(T * p)
{
if(p) intrusive_ptr_release(p);
}
};
shared_ptr&lt;X&gt; make_shared_from_intrusive(X * p)
{
if(p) intrusive_ptr_add_ref(p);
shared_ptr&lt;X&gt; px(p, intrusive_deleter&lt;X&gt;());
return px;
}
</pre>
<h2><A name="another_sp">Using a <code>shared_ptr</code> to hold another shared
ownership smart pointer</A></h2>
<p>One of the design goals of <code>shared_ptr</code> is to be used in library
interfaces. It is possible to encounter a situation where a library takes a <code>shared_ptr</code>
argument, but the object at hand is being managed by a different reference
counted or linked smart pointer.</p>
<P>It is possible to exploit <code>shared_ptr</code>'s custom deleter feature to
wrap this existing smart pointer behind a <code>shared_ptr</code> facade:</P>
<pre>template&lt;class P&gt; struct smart_pointer_deleter
{
private:
P p_;
public:
smart_pointer_deleter(P const &amp; p): p_(p)
{
}
void operator()(void const *)
{
p_.reset();
}
P const &amp; get() const
{
return p_;
}
};
shared_ptr&lt;X&gt; make_shared_from_another(another_ptr&lt;X&gt; qx)
{
shared_ptr&lt;X&gt; px(qx.get(), smart_pointer_deleter&lt; another_ptr&lt;X&gt; &gt;(qx));
return px;
}
</pre>
<p>One subtle point is that deleters are not allowed to throw exceptions, and the
above example as written assumes that <code>p_.reset()</code> doesn't throw. If
this is not the case, <code>p_.reset()</code> should be wrapped in a <code>try {}
catch(...) {}</code> block that ignores exceptions. In the (usually
unlikely) event when an exception is thrown and ignored, <code>p_</code> will
be released when the lifetime of the deleter ends. This happens when all
references, including weak pointers, are destroyed or reset.</p>
<P>Another twist is that it is possible, given the above <code>shared_ptr</code> instance,
to recover the original smart pointer, using <code><A href="shared_ptr.htm#get_deleter">
get_deleter</A></code>:</P>
<pre>void extract_another_from_shared(shared_ptr&lt;X&gt; px)
{
typedef smart_pointer_deleter&lt; another_ptr&lt;X&gt; &gt; deleter;
if(deleter const * pd = get_deleter&lt;deleter&gt;(px))
{
another_ptr&lt;X&gt; qx = pd-&gt;get();
}
else
{
// not one of ours
}
}
</pre>
<h2><A name="from_raw">Obtaining a <code>shared_ptr</code> from a raw pointer</A></h2>
<p>Sometimes it is necessary to obtain a <code>shared_ptr</code> given a raw
pointer to an object that is already managed by another <code>shared_ptr</code>
instance. Example:</p>
<pre>void f(X * p)
{
shared_ptr&lt;X&gt; px(<i>???</i>);
}
</pre>
<p>Inside <code>f</code>, we'd like to create a <code>shared_ptr</code> to <code>*p</code>.</p>
<P>In the general case, this problem has no solution. One approach is to modify <code>f</code>
to take a <code>shared_ptr</code>, if possible:</P>
<pre>void f(shared_ptr&lt;X&gt; px);
</pre>
<p>The same transformation can be used for nonvirtual member functions, to convert
the implicit <code>this</code>:</p>
<pre>void X::f(int m);
</pre>
<p>would become a free function with a <code>shared_ptr</code> first argument:</p>
<pre>void f(shared_ptr&lt;X&gt; this_, int m);
</pre>
<p>If <code>f</code> cannot be changed, but <code>X</code> uses intrusive counting,
use <code><A href="#intrusive">make_shared_from_intrusive</A></code> described
above. Or, if it's known that the <code>shared_ptr</code> created in <code>f</code>
will never outlive the object, use <A href="#static">a null deleter</A>.</p>
<h2><A name="in_constructor">Obtaining a <code>shared_ptr</code> (<code>weak_ptr</code>)
to <code>this</code> in a constructor</A></h2>
<p>Some designs require objects to register themselves on construction with a
central authority. When the registration routines take a shared_ptr, this leads
to the question how could a constructor obtain a shared_ptr to this:</p>
<pre>class X
{
public:
X()
{
shared_ptr&lt;X&gt; this_(<i>???</i>);
}
};
</pre>
<p>In the general case, the problem cannot be solved. The <code>X</code> instance
being constructed can be an automatic variable or a static variable; it can be
created on the heap:</p>
<pre>shared_ptr&lt;X&gt; px(new X);</pre>
<P>but at construction time, <code>px</code> does not exist yet, and it is
impossible to create another <code>shared_ptr</code> instance that shares
ownership with it.</P>
<P>Depending on context, if the inner <code>shared_ptr</code> <code>this_</code> doesn't
need to keep the object alive, use a <code>null_deleter</code> as explained <A href="#static">
here</A> and <A href="#weak_without_shared">here</A>. If <code>X</code> is
supposed to always live on the heap, and be managed by a <code>shared_ptr</code>,
use a static factory function:</P>
<pre>class X
{
private:
X() { ... }
public:
static shared_ptr&lt;X&gt; create()
{
shared_ptr&lt;X&gt; px(new X);
// use px as 'this_'
return px;
}
};
</pre>
<h2><A name="from_this">Obtaining a <code>shared_ptr</code> to <code>this</code></A></h2>
<p>Sometimes it is needed to obtain a <code>shared_ptr</code> from <code>this</code>
in a virtual member function under the assumption that <code>this</code> is
already managed by a <code>shared_ptr</code>. The transformations <A href="#from_raw">
described in the previous technique</A> cannot be applied.</p>
<P>A typical example:</P>
<pre>class X
{
public:
virtual void f() = 0;
protected:
~X() {}
};
class Y
{
public:
virtual shared_ptr&lt;X&gt; getX() = 0;
protected:
~Y() {}
};
// --
class impl: public X, public Y
{
public:
impl() { ... }
virtual void f() { ... }
virtual shared_ptr&lt;X&gt; getX()
{
shared_ptr&lt;X&gt; px(<i>???</i>);
return px;
}
};
</pre>
<p>The solution is to keep a weak pointer to <code>this</code> as a member in <code>impl</code>:</p>
<pre>class impl: public X, public Y
{
private:
weak_ptr&lt;impl&gt; weak_this;
impl(impl const &amp;);
impl &amp; operator=(impl const &amp;);
impl() { ... }
public:
static shared_ptr&lt;impl&gt; create()
{
shared_ptr&lt;impl&gt; pi(new impl);
pi-&gt;weak_this = pi;
return pi;
}
virtual void f() { ... }
virtual shared_ptr&lt;X&gt; getX()
{
shared_ptr&lt;X&gt; px(weak_this);
return px;
}
};
</pre>
<p>The library now includes a helper class template <code><A href="enable_shared_from_this.html">
enable_shared_from_this</A></code> that can be used to encapsulate the
solution:</p>
<pre>class impl: public X, public Y, public enable_shared_from_this&lt;impl&gt;
{
public:
impl(impl const &amp;);
impl &amp; operator=(impl const &amp;);
public:
virtual void f() { ... }
virtual shared_ptr&lt;X&gt; getX()
{
return shared_from_this();
}
}
</pre>
<p>Note that you no longer need to manually initialize the <code>weak_ptr</code> member
in <code><A href="enable_shared_from_this.html">enable_shared_from_this</A></code>.
Constructing a <code>shared_ptr</code> to <code>impl</code> takes care of that.</p>
<h2><A name="handle">Using <code>shared_ptr</code> as a smart counted handle</A></h2>
<p>Some library interfaces use opaque handles, a variation of the <A href="#incomplete">
incomplete class technique</A> described above. An example:</p>
<pre>typedef void * HANDLE;
HANDLE CreateProcess();
void CloseHandle(HANDLE);
</pre>
<p>Instead of a raw pointer, it is possible to use <code>shared_ptr</code> as the
handle and get reference counting and automatic resource management for free:</p>
<pre>typedef shared_ptr&lt;void&gt; handle;
handle createProcess()
{
shared_ptr&lt;void&gt; pv(CreateProcess(), CloseHandle);
return pv;
}
</pre>
<h2><A name="on_block_exit">Using <code>shared_ptr</code> to execute code on block exit</A></h2>
<p><code>shared_ptr&lt;void&gt;</code> can automatically execute cleanup code when
control leaves a scope.</p>
<UL>
<LI>
Executing <code>f(p)</code>, where <code>p</code> is a pointer:</LI></UL>
<pre> shared_ptr&lt;void&gt; guard(p, f);
</pre>
<UL>
<LI>
Executing arbitrary code: <code>f(x, y)</code>:</LI></UL>
<pre> shared_ptr&lt;void&gt; guard(static_cast&lt;void*&gt;(0), <A href="../bind/bind.html" >bind</A>(f, x, y));
</pre>
<P>For a more thorough treatment, see the article "Simplify Your Exception-Safe
Code" by Andrei Alexandrescu and Petru Marginean, available online at <A href="http://www.cuj.com/experts/1812/alexandr.htm?topic=experts">
http://www.cuj.com/experts/1812/alexandr.htm?topic=experts</A>.</P>
<h2><A name="pvoid">Using <code>shared_ptr&lt;void&gt;</code> to hold an arbitrary
object</A></h2>
<p><code>shared_ptr&lt;void&gt;</code> can act as a generic object pointer similar
to <code>void*</code>. When a <code>shared_ptr&lt;void&gt;</code> instance
constructed as:</p>
<pre> shared_ptr&lt;void&gt; pv(new X);
</pre>
<p>is destroyed, it will correctly dispose of the <code>X</code> object by
executing <code>~X</code>.</p>
<p>This propery can be used in much the same manner as a raw <code>void*</code> is
used to temporarily strip type information from an object pointer. A <code>shared_ptr&lt;void&gt;</code>
can later be cast back to the correct type by using <code><A href="shared_ptr.htm#static_pointer_cast">
static_pointer_cast</A></code>.</p>
<h2><A name="extra_data">Associating arbitrary data with heterogeneous <code>shared_ptr</code>
instances</A></h2>
<p><code>shared_ptr</code> and <code>weak_ptr</code> support <code>operator&lt;</code>
comparisons required by standard associative containers such as <code>std::map</code>.
This can be used to non-intrusively associate arbitrary data with objects
managed by <code>shared_ptr</code>:</p>
<pre>typedef int Data;
std::map&lt; shared_ptr&lt;void&gt;, Data &gt; userData;
// or std::map&lt; weak_ptr&lt;void&gt;, Data &gt; userData; to not affect the lifetime
shared_ptr&lt;X&gt; px(new X);
shared_ptr&lt;int&gt; pi(new int(3));
userData[px] = 42;
userData[pi] = 91;
</pre>
<h2><A name="as_lock">Using <code>shared_ptr</code> as a CopyConstructible mutex lock</A></h2>
<p>Sometimes it's necessary to return a mutex lock from a function, and a
noncopyable lock cannot be returned by value. It is possible to use <code>shared_ptr</code>
as a mutex lock:</p>
<pre>class mutex
{
public:
void lock();
void unlock();
};
shared_ptr&lt;mutex&gt; lock(mutex &amp; m)
{
m.lock();
return shared_ptr&lt;mutex&gt;(&amp;m, mem_fn(&amp;mutex::unlock));
}
</pre>
<p>Better yet, the <code>shared_ptr</code> instance acting as a lock can be
encapsulated in a dedicated <code>shared_lock</code> class:</p>
<pre>class shared_lock
{
private:
shared_ptr&lt;void&gt; pv;
public:
template&lt;class Mutex&gt; explicit shared_lock(Mutex &amp; m): pv((m.lock(), &amp;m), mem_fn(&amp;Mutex::unlock)) {}
};
</pre>
<p><code>shared_lock</code> can now be used as:</p>
<pre> shared_lock lock(m);
</pre>
<p>Note that <code>shared_lock</code> is not templated on the mutex type, thanks to <code>
shared_ptr&lt;void&gt;</code>'s ability to hide type information.</p>
<h2><A name="wrapper">Using <code>shared_ptr</code> to wrap member function calls</A></h2>
<p><code>shared_ptr</code> implements the ownership semantics required from the <code>Wrap</code>/<code>CallProxy</code>
scheme described in Bjarne Stroustrup's article "Wrapping C++ Member Function
Calls" (available online at <A href="http://www.research.att.com/~bs/wrapper.pdf">http://www.research.att.com/~bs/wrapper.pdf</A>).
An implementation is given below:</p>
<pre>template&lt;class T&gt; class pointer
{
private:
T * p_;
public:
explicit pointer(T * p): p_(p)
{
}
shared_ptr&lt;T&gt; operator-&gt;() const
{
p_-&gt;prefix();
return shared_ptr&lt;T&gt;(p_, <A href="../bind/mem_fn.html" >mem_fn</A>(&amp;T::suffix));
}
};
class X
{
private:
void prefix();
void suffix();
friend class pointer&lt;X&gt;;
public:
void f();
void g();
};
int main()
{
X x;
pointer&lt;X&gt; px(&amp;x);
px-&gt;f();
px-&gt;g();
}
</pre>
<h2><A name="delayed">Delayed deallocation</A></h2>
<p>In some situations, a single <code>px.reset()</code> can trigger an expensive
deallocation in a performance-critical region:</p>
<pre>class X; // ~X is expensive
class Y
{
shared_ptr&lt;X&gt; px;
public:
void f()
{
px.reset();
}
};
</pre>
<p>The solution is to postpone the potential deallocation by moving <code>px</code>
to a dedicated free list that can be periodically emptied when performance and
response times are not an issue:</p>
<pre>vector&lt; shared_ptr&lt;void&gt; &gt; free_list;
class Y
{
shared_ptr&lt;X&gt; px;
public:
void f()
{
free_list.push_back(px);
px.reset();
}
};
// periodically invoke free_list.clear() when convenient
</pre>
<p>Another variation is to move the free list logic to the construction point by
using a delayed deleter:</p>
<pre>struct delayed_deleter
{
template&lt;class T&gt; void operator()(T * p)
{
try
{
shared_ptr&lt;void&gt; pv(p);
free_list.push_back(pv);
}
catch(...)
{
}
}
};
</pre>
<h2><A name="weak_without_shared">Weak pointers to objects not managed by a <code>shared_ptr</code></A></h2>
<p>Make the object hold a <code>shared_ptr</code> to itself, using a <code>null_deleter</code>:</p>
<pre>class X
{
private:
shared_ptr&lt;X&gt; this_;
int i_;
public:
explicit X(int i): this_(this, null_deleter()), i_(i)
{
}
// repeat in all constructors (including the copy constructor!)
X(X const &amp; rhs): this_(this, null_deleter()), i_(rhs.i_)
{
}
// do not forget to not assign this_ in the copy assignment
X &amp; operator=(X const &amp; rhs)
{
i_ = rhs.i_;
}
weak_ptr&lt;X&gt; get_weak_ptr() const { return this_; }
};
</pre>
<p>When the object's lifetime ends, <code>X::this_</code> will be destroyed, and
all weak pointers will automatically expire.</p>
<hr>
<p>$Date$</p>
<p><small>Copyright <20> 2003 Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

270
src/sp_collector.cpp Normal file
View File

@@ -0,0 +1,270 @@
//
// sp_collector.cpp
//
// Copyright (c) 2002, 2003 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
#include <boost/assert.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/detail/lightweight_mutex.hpp>
#include <cstdlib>
#include <map>
#include <deque>
#include <iostream>
typedef std::map< void const *, std::pair<void *, size_t> > map_type;
static map_type & get_map()
{
static map_type m;
return m;
}
typedef boost::detail::lightweight_mutex mutex_type;
static mutex_type & get_mutex()
{
static mutex_type m;
return m;
}
static void * init_mutex_before_main = &get_mutex();
namespace
{
class X;
struct count_layout
{
boost::detail::sp_counted_base * pi;
int id;
};
struct shared_ptr_layout
{
X * px;
count_layout pn;
};
}
// assume 4 byte alignment for pointers when scanning
size_t const pointer_align = 4;
typedef std::map<void const *, long> map2_type;
static void scan_and_count(void const * area, size_t size, map_type const & m, map2_type & m2)
{
unsigned char const * p = static_cast<unsigned char const *>(area);
for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
{
shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p);
if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m.count(q->pn.pi) != 0)
{
++m2[q->pn.pi];
}
}
}
typedef std::deque<void const *> open_type;
static void scan_and_mark(void const * area, size_t size, map2_type & m2, open_type & open)
{
unsigned char const * p = static_cast<unsigned char const *>(area);
for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
{
shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p);
if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0)
{
open.push_back(q->pn.pi);
m2.erase(q->pn.pi);
}
}
}
static void find_unreachable_objects_impl(map_type const & m, map2_type & m2)
{
// scan objects for shared_ptr members, compute internal counts
{
std::cout << "... " << m.size() << " objects in m.\n";
for(map_type::const_iterator i = m.begin(); i != m.end(); ++i)
{
boost::detail::sp_counted_base const * p = static_cast<boost::detail::sp_counted_base const *>(i->first);
BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map
m2[ i->first ];
scan_and_count(i->second.first, i->second.second, m, m2);
}
std::cout << "... " << m2.size() << " objects in m2.\n";
}
// mark reachable objects
{
open_type open;
for(map2_type::iterator i = m2.begin(); i != m2.end(); ++i)
{
boost::detail::sp_counted_base const * p = static_cast<boost::detail::sp_counted_base const *>(i->first);
if(p->use_count() != i->second) open.push_back(p);
}
std::cout << "... " << open.size() << " objects in open.\n";
for(open_type::iterator j = open.begin(); j != open.end(); ++j)
{
m2.erase(*j);
}
while(!open.empty())
{
void const * p = open.front();
open.pop_front();
map_type::const_iterator i = m.find(p);
BOOST_ASSERT(i != m.end());
scan_and_mark(i->second.first, i->second.second, m2, open);
}
}
// m2 now contains the unreachable objects
}
std::size_t find_unreachable_objects(bool report)
{
map2_type m2;
#ifdef BOOST_HAS_THREADS
// This will work without the #ifdef, but some compilers warn
// that lock is not referenced
mutex_type::scoped_lock lock(get_mutex());
#endif
map_type const & m = get_map();
find_unreachable_objects_impl(m, m2);
if(report)
{
for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j)
{
map_type::const_iterator i = m.find(j->first);
BOOST_ASSERT(i != m.end());
std::cout << "Unreachable object at " << i->second.first << ", " << i->second.second << " bytes long.\n";
}
}
return m2.size();
}
typedef std::deque< boost::shared_ptr<X> > free_list_type;
static void scan_and_free(void * area, size_t size, map2_type const & m2, free_list_type & free)
{
unsigned char * p = static_cast<unsigned char *>(area);
for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align)
{
shared_ptr_layout * q = reinterpret_cast<shared_ptr_layout *>(p);
if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0 && q->px != 0)
{
boost::shared_ptr<X> * ppx = reinterpret_cast< boost::shared_ptr<X> * >(p);
free.push_back(*ppx);
ppx->reset();
}
}
}
void free_unreachable_objects()
{
free_list_type free;
{
map2_type m2;
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(get_mutex());
#endif
map_type const & m = get_map();
find_unreachable_objects_impl(m, m2);
for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j)
{
map_type::const_iterator i = m.find(j->first);
BOOST_ASSERT(i != m.end());
scan_and_free(i->second.first, i->second.second, m2, free);
}
}
std::cout << "... about to free " << free.size() << " objects.\n";
}
// debug hooks
namespace boost
{
void sp_scalar_constructor_hook(void *)
{
}
void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn)
{
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(get_mutex());
#endif
get_map()[pn] = std::make_pair(px, size);
}
void sp_scalar_destructor_hook(void *)
{
}
void sp_scalar_destructor_hook(void *, std::size_t, void * pn)
{
#ifdef BOOST_HAS_THREADS
mutex_type::scoped_lock lock(get_mutex());
#endif
get_map().erase(pn);
}
void sp_array_constructor_hook(void *)
{
}
void sp_array_destructor_hook(void *)
{
}
} // namespace boost
#endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)

243
src/sp_debug_hooks.cpp Normal file
View File

@@ -0,0 +1,243 @@
//
// sp_debug_hooks.cpp
//
// Copyright (c) 2002, 2003 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
#include <boost/assert.hpp>
#include <new>
#include <cstdlib>
int const m = 2; // m * sizeof(int) must be aligned appropriately
// magic values to mark heap blocks with
int const allocated_scalar = 0x1234560C;
int const allocated_array = 0x1234560A;
int const adopted_scalar = 0x0567890C;
int const adopted_array = 0x0567890A;
int const deleted = 0x498769DE;
using namespace std; // for compilers where things aren't in std
// operator new
static new_handler get_new_handler()
{
new_handler p = set_new_handler(0);
set_new_handler(p);
return p;
}
static void * allocate(size_t n, int mark)
{
int * pm;
for(;;)
{
pm = static_cast<int*>(malloc(n + m * sizeof(int)));
if(pm != 0) break;
if(new_handler pnh = get_new_handler())
{
pnh();
}
else
{
return 0;
}
}
*pm = mark;
return pm + m;
}
void * operator new(size_t n) throw(bad_alloc)
{
void * p = allocate(n, allocated_scalar);
#if !defined(BOOST_NO_EXCEPTIONS)
if(p == 0) throw bad_alloc();
#endif
return p;
}
#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
void * operator new(size_t n, nothrow_t const &) throw()
{
return allocate(n, allocated_scalar);
}
#endif
void * operator new[](size_t n) throw(bad_alloc)
{
void * p = allocate(n, allocated_array);
#if !defined(BOOST_NO_EXCEPTIONS)
if(p == 0) throw bad_alloc();
#endif
return p;
}
#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
void * operator new[](size_t n, nothrow_t const &) throw()
{
return allocate(n, allocated_array);
}
#endif
// debug hooks
namespace boost
{
void sp_scalar_constructor_hook(void * p)
{
if(p == 0) return;
int * pm = static_cast<int*>(p);
pm -= m;
BOOST_ASSERT(*pm != adopted_scalar); // second smart pointer to the same address
BOOST_ASSERT(*pm != allocated_array); // allocated with new[]
BOOST_ASSERT(*pm == allocated_scalar); // not allocated with new
*pm = adopted_scalar;
}
void sp_scalar_constructor_hook(void * px, std::size_t, void *)
{
sp_scalar_constructor_hook(px);
}
void sp_scalar_destructor_hook(void * p)
{
if(p == 0) return;
int * pm = static_cast<int*>(p);
pm -= m;
BOOST_ASSERT(*pm == adopted_scalar); // attempt to destroy nonmanaged block
*pm = allocated_scalar;
}
void sp_scalar_destructor_hook(void * px, std::size_t, void *)
{
sp_scalar_destructor_hook(px);
}
// It is not possible to handle the array hooks in a portable manner.
// The implementation typically reserves a bit of storage for the number
// of objects in the array, and the argument of the array hook isn't
// equal to the return value of operator new[].
void sp_array_constructor_hook(void * /* p */)
{
/*
if(p == 0) return;
// adjust p depending on the implementation
int * pm = static_cast<int*>(p);
pm -= m;
BOOST_ASSERT(*pm != adopted_array); // second smart array pointer to the same address
BOOST_ASSERT(*pm != allocated_scalar); // allocated with new
BOOST_ASSERT(*pm == allocated_array); // not allocated with new[]
*pm = adopted_array;
*/
}
void sp_array_destructor_hook(void * /* p */)
{
/*
if(p == 0) return;
// adjust p depending on the implementation
int * pm = static_cast<int*>(p);
pm -= m;
BOOST_ASSERT(*pm == adopted_array); // attempt to destroy nonmanaged block
*pm = allocated_array;
*/
}
} // namespace boost
// operator delete
void operator delete(void * p) throw()
{
if(p == 0) return;
int * pm = static_cast<int*>(p);
pm -= m;
BOOST_ASSERT(*pm != deleted); // double delete
BOOST_ASSERT(*pm != adopted_scalar); // delete p.get();
BOOST_ASSERT(*pm != allocated_array); // allocated with new[]
BOOST_ASSERT(*pm == allocated_scalar); // not allocated with new
*pm = deleted;
free(pm);
}
#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
void operator delete(void * p, nothrow_t const &) throw()
{
::operator delete(p);
}
#endif
void operator delete[](void * p) throw()
{
if(p == 0) return;
int * pm = static_cast<int*>(p);
pm -= m;
BOOST_ASSERT(*pm != deleted); // double delete
BOOST_ASSERT(*pm != adopted_scalar); // delete p.get();
BOOST_ASSERT(*pm != allocated_scalar); // allocated with new
BOOST_ASSERT(*pm == allocated_array); // not allocated with new[]
*pm = deleted;
free(pm);
}
#if !defined(__BORLANDC__) || (__BORLANDC__ > 0x551)
void operator delete[](void * p, nothrow_t const &) throw()
{
::operator delete[](p);
}
#endif
#endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS)

67
test/Jamfile.v2 Normal file
View File

@@ -0,0 +1,67 @@
# Boost.SmartPtr Library test Jamfile
#
# Copyright (c) 2003-2007 Peter Dimov
# Copyright (c) 2003 Dave Abrahams
#
# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# bring in rules for testing
import testing ;
{
test-suite "smart_ptr"
: [ run smart_ptr_test.cpp ]
[ run shared_ptr_basic_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ]
[ run shared_ptr_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ]
[ run weak_ptr_test.cpp ]
[ run weak_ptr_move_test.cpp ]
[ run shared_from_this_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ]
[ run get_deleter_test.cpp ]
[ run intrusive_ptr_test.cpp ]
[ run intrusive_ptr_move_test.cpp ]
[ run atomic_count_test.cpp ]
[ run lw_mutex_test.cpp ]
[ compile-fail shared_ptr_assign_fail.cpp ]
[ compile-fail shared_ptr_delete_fail.cpp ]
[ compile-fail shared_ptr_compare_fail.cpp ]
[ run shared_ptr_alloc2_test.cpp ]
[ run pointer_cast_test.cpp ]
[ compile pointer_to_other_test.cpp ]
[ run auto_ptr_rv_test.cpp ]
[ run shared_ptr_alias_test.cpp ]
[ run shared_ptr_rv_test.cpp ]
[ run shared_ptr_move_test.cpp ]
[ compile-fail shared_ptr_pv_fail.cpp ]
[ run sp_unary_addr_test.cpp ]
[ compile-fail scoped_ptr_eq_fail.cpp ]
[ compile-fail scoped_array_eq_fail.cpp ]
[ run esft_regtest.cpp ]
[ run yield_k_test.cpp ]
[ run yield_k_test.cpp : : : <threading>multi : yield_k_test.mt ]
[ run spinlock_test.cpp ]
[ run spinlock_try_test.cpp ]
[ run spinlock_try_test.cpp : : : <threading>multi : spinlock_try_test.mt ]
[ run spinlock_pool_test.cpp ]
[ run make_shared_test.cpp ]
[ run make_shared_perfect_forwarding_test.cpp ]
[ run sp_convertible_test.cpp ]
[ run wp_convertible_test.cpp ]
[ run ip_convertible_test.cpp ]
[ run allocate_shared_test.cpp ]
[ run sp_atomic_test.cpp ]
[ run esft_void_test.cpp ]
[ run esft_second_ptr_test.cpp ]
[ run make_shared_esft_test.cpp ]
[ run allocate_shared_esft_test.cpp ]
[ run sp_recursive_assign_test.cpp ]
[ run sp_recursive_assign2_test.cpp ]
[ run sp_recursive_assign_rv_test.cpp ]
[ run sp_recursive_assign2_rv_test.cpp ]
[ run esft_constructor_test.cpp ]
[ compile-fail auto_ptr_lv_fail.cpp ]
[ run atomic_count_test2.cpp ]
[ run sp_typeinfo_test.cpp ]
;
}

View File

@@ -0,0 +1,264 @@
// allocate_shared_esft_test.cpp
//
// Copyright 2007-2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/lightweight_test.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <memory>
class X: public boost::enable_shared_from_this<X>
{
private:
X( X const & );
X & operator=( X const & );
public:
static int instances;
explicit X( int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0, int = 0 )
{
++instances;
}
~X()
{
--instances;
}
};
int X::instances = 0;
int main()
{
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>() );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > px = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
BOOST_TEST( X::instances == 1 );
try
{
boost::shared_ptr< X > qx = px->shared_from_this();
BOOST_TEST( px == qx );
BOOST_TEST( !( px < qx ) && !( qx < px ) );
px.reset();
BOOST_TEST( X::instances == 1 );
}
catch( boost::bad_weak_ptr const& )
{
BOOST_ERROR( "px->shared_from_this() failed" );
}
}
BOOST_TEST( X::instances == 0 );
return boost::report_errors();
}

View File

@@ -0,0 +1,204 @@
// allocate_shared_test.cpp
//
// Copyright 2007-2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/lightweight_test.hpp>
#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <cstddef>
class X
{
private:
X( X const & );
X & operator=( X const & );
void * operator new( std::size_t n )
{
// lack of this definition causes link errors on Comeau C++
BOOST_ERROR( "private X::new called" );
return ::operator new( n );
}
void operator delete( void * p )
{
// lack of this definition causes link errors on MSVC
BOOST_ERROR( "private X::delete called" );
::operator delete( p );
}
public:
static int instances;
int v;
explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
{
++instances;
}
~X()
{
--instances;
}
};
int X::instances = 0;
int main()
{
{
boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator<int>() );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( *pi == 0 );
}
{
boost::shared_ptr< int > pi = boost::allocate_shared< int >( std::allocator<int>(), 5 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( *pi == 5 );
}
BOOST_TEST( X::instances == 0 );
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>() );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 0 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::shared_ptr< X > pi = boost::allocate_shared< X >( std::allocator<void>(), 1, 2, 3, 4, 5, 6, 7, 8, 9 );
boost::weak_ptr<X> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
return boost::report_errors();
}

View File

@@ -0,0 +1,40 @@
//
// atomic_count_test.cpp
//
// Copyright 2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/atomic_count.hpp>
#include <boost/detail/lightweight_test.hpp>
int main()
{
boost::detail::atomic_count n( 4 );
BOOST_TEST( n == 4L );
++n;
BOOST_TEST( n == 5L );
BOOST_TEST( --n != 0L );
boost::detail::atomic_count m( 0 );
BOOST_TEST( m == 0 );
++m;
BOOST_TEST( m == 1 );
++m;
BOOST_TEST( m == 2 );
BOOST_TEST( --m != 0 );
BOOST_TEST( --m == 0 );
return boost::report_errors();
}

View File

@@ -0,0 +1,55 @@
//
// atomic_count_test2.cpp
//
// Copyright 2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/detail/atomic_count.hpp>
#include <boost/detail/lightweight_test.hpp>
int main()
{
boost::detail::atomic_count n( 4 );
BOOST_TEST( n == 4 );
BOOST_TEST( ++n == 5 );
BOOST_TEST( ++n == 6 );
BOOST_TEST( n == 6 );
BOOST_TEST( --n == 5 );
BOOST_TEST( --n == 4 );
BOOST_TEST( n == 4 );
boost::detail::atomic_count m( 0 );
BOOST_TEST( m == 0 );
BOOST_TEST( ++m == 1 );
BOOST_TEST( ++m == 2 );
BOOST_TEST( m == 2 );
BOOST_TEST( --m == 1 );
BOOST_TEST( --m == 0 );
BOOST_TEST( m == 0 );
BOOST_TEST( --m == -1 );
BOOST_TEST( --m == -2 );
BOOST_TEST( m == -2 );
BOOST_TEST( ++m == -1 );
BOOST_TEST( ++m == 0 );
BOOST_TEST( m == 0 );
return boost::report_errors();
}

32
test/auto_ptr_lv_fail.cpp Normal file
View File

@@ -0,0 +1,32 @@
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// auto_ptr_lv_fail.cpp - a negative test for converting an auto_ptr to shared_ptr
//
// Copyright 2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/shared_ptr.hpp>
#include <memory>
void f( boost::shared_ptr<int> )
{
}
int main()
{
std::auto_ptr<int> p;
f( p ); // must fail
return 0;
}

Some files were not shown because too many files have changed in this diff Show More