Compare commits

..

388 Commits

Author SHA1 Message Date
Peter Dimov
169c0cd52a Remove lwm_nop.hpp; add lwm_std_mutex.hpp 2020-01-08 03:57:13 +02:00
Peter Dimov
7d70691a16 Remove Windows Runtime workaround from yield_k.hpp; it's no longer relevant, Sleep is available 2020-01-08 03:09:11 +02:00
Peter Dimov
90c27d7cfa Remove Windows Runtime workaround from lwm_win32_cs.hpp; it's no longer relevant, InitializeCriticalSection is available 2020-01-08 02:55:14 +02:00
Glen Fernandes
43d1fe12c5 Include lightweight_test from core and workaround from config 2020-01-01 08:31:25 -05:00
Peter Dimov
a2749dddb4 Disable 32 bit clang-win to avoid mspdbcore.dll errors 2019-12-05 15:49:48 +02:00
Peter Dimov
a71e62146c Add VS2019 to Appveyor; separate clang-win into its own job 2019-11-24 00:05:38 +02:00
Glen Fernandes
274ec17836 Even more documentation corrections 2019-09-15 02:06:23 -04:00
Glen Fernandes
a7341070f1 More documentation corrections 2019-09-03 11:53:42 -04:00
Glen Fernandes
a6323354cd Update constraints and synopsis in documentation 2019-09-02 22:10:09 -04:00
Glen Fernandes
f788448101 Document alloc_deleter 2019-08-30 12:52:50 -04:00
Glen Fernandes
283f2d2a11 Simplify synopsis using alias template 2019-08-30 12:04:09 -04:00
Glen Fernandes
034f94617d Workaround for VC10 unique_ptr operator-> 2019-08-30 12:03:36 -04:00
Glen Fernandes
6a5f67b3a2 Disable tests on VC10 which lacks conforming unique_ptr 2019-08-30 10:50:56 -04:00
Glen Fernandes
dcd3c8ef80 In test cases, include allocate_unique first 2019-08-30 08:17:54 -04:00
Glen Fernandes
bb2a453ff6 Add additional test cases 2019-08-30 08:16:11 -04:00
Glen Fernandes
e56eec70ca Call to_address in the scalar destroy case too 2019-08-30 07:39:02 -04:00
Glen Fernandes
60c26acab8 Implement allocate_unique 2019-08-30 00:31:28 -04:00
Peter Dimov
00f6b5dcb0 Split gcc 8/9 Travis jobs (again) due to log size 2019-08-29 13:20:36 +03:00
Peter Dimov
6195ae1eb0 Disable -Wdelete-non-virtual-dtor 2019-08-29 12:27:51 +03:00
Peter Dimov
30291c406a Update .travis.yml 2019-08-29 01:01:52 +03:00
Peter Dimov
610f19f247 Merge pull request #69 from CJBussey/feature/fix_warning_implicit_conversion
atomic_count_std_atomic: static_cast v to std::int_least32_t
2019-06-23 04:21:52 -07:00
Carl Bussey
876d40a9ab atomic_count_std_atomic: static_cast v to std::int_least32_t
* fix implicit conversion warning
2019-06-18 11:44:17 +02:00
Peter Dimov
e4d642c46a Revert Travis to Trusty 2019-05-30 02:42:39 +03:00
Glen Fernandes
3dffa64f58 Bind allocator to element type, not scalar type 2019-05-15 07:33:04 -04:00
Glen Fernandes
af92bd89ef allocation_ptr will be modified, renamed, and moved to detail 2019-05-05 22:21:22 -04:00
Glen Fernandes
4742143605 Support allocation_ptr of const and volatile types 2019-05-04 09:43:11 -04:00
Glen Fernandes
872bf10347 Move construct and destroy from Smart_Ptr to Core 2019-05-03 17:39:25 -04:00
Glen Fernandes
c0ae9b3728 Implement allocation_ptr 2019-05-02 19:26:29 -04:00
Glen Fernandes
1298c2e8e5 Include sp_noexcept.hpp in sp_construct.hpp 2019-05-02 18:00:53 -04:00
Glen Fernandes
d593061b15 Move construct and destroy utilities to common header 2019-05-02 09:48:45 -04:00
Glen Fernandes
5072045f12 Use boost::noinit_adapt free function 2019-04-29 00:37:55 -04:00
Glen Fernandes
442e179920 Simplify implementation in terms of noinit_adaptor 2019-04-28 22:42:37 -04:00
Peter Dimov
9544a8cb91 Add revision history for 1.65 2019-04-24 17:21:37 +03:00
Peter Dimov
5823d6bcc9 Document enable_shared_from 2019-04-24 05:16:03 +03:00
Peter Dimov
f56e609757 Fix mistake in weak_from_this_test 2019-04-24 04:57:37 +03:00
Peter Dimov
8df63a3d0e Add tests for enable_shared_from 2019-04-24 04:50:59 +03:00
Peter Dimov
4b6cb1223b Add boost/smart_ptr/enable_shared_from.hpp 2019-04-24 04:50:30 +03:00
Peter Dimov
719e819570 Under g++ 4.4, <memory> doesn't compile with rtti=off 2019-04-22 15:57:56 +03:00
Peter Dimov
a571b3a250 Only include core/typeinfo.hpp when needed 2019-04-22 06:07:36 +03:00
Peter Dimov
f17c5e8e3b Add a few no_rtti tests 2019-04-22 05:43:08 +03:00
Peter Dimov
e306b30dcf Use a private detail/sp_typeinfo header instead of the deprecated Core one 2019-04-22 05:25:07 +03:00
Peter Dimov
b6b49ef591 Split g++ 8 Travis job, because log length 2019-04-22 02:19:27 +03:00
Peter Dimov
2122c7753c Avoid memcpy over a spinlock, because g++ 8 warns 2019-04-22 02:17:28 +03:00
Peter Dimov
7c76fb385d Add clang-win to Appveyor 2019-04-22 00:59:38 +03:00
Peter Dimov
372fac679b Remove _internal_aliasing_assign 2019-04-21 23:13:06 +03:00
Peter Dimov
e3adcaed1e Add revision history 2019-04-21 23:00:24 +03:00
Peter Dimov
016e682af6 Document weak_ptr aliasing constructors and empty 2019-04-21 22:52:44 +03:00
Peter Dimov
78e095d761 Disable tests that don't compile on msvc-8.0 2019-04-21 22:50:24 +03:00
Peter Dimov
eb8a91cb46 Add tests for the weak_ptr aliasing constructors 2019-04-21 22:44:09 +03:00
Peter Dimov
513cd15378 Add aliasing constructors to weak_ptr. Closes #67. 2019-04-21 22:43:04 +03:00
Peter Dimov
7bfa6a1f3d Fix typo 2019-04-21 21:33:55 +03:00
Peter Dimov
8120bb44cb Add rvalue pointer casts (closes #66) 2019-04-21 00:47:36 +03:00
Peter Dimov
18974ea2db Add cast tests to intrusive_ptr_test 2019-04-20 18:54:13 +03:00
Peter Dimov
2a4aca403a Merge branch 'develop' into feature/intrusive-ptr-tests 2019-04-20 18:15:31 +03:00
Peter Dimov
4d0d81477c Update msvc workarounds for 14.2 2019-04-20 18:15:05 +03:00
Peter Dimov
1725e26f70 Add assignment tests to intrusive_ptr_test 2019-04-20 18:02:11 +03:00
Peter Dimov
47fffaf11c Switch Appveyor to 2015 image 2019-04-14 18:24:21 +03:00
Peter Dimov
7f0323a347 Merge branch 'develop' of https://github.com/boostorg/smart_ptr into develop 2019-03-25 19:25:44 +02:00
Peter Dimov
6d8ea0f0c4 Remove project-id from doc/Jamfile 2019-03-25 19:25:33 +02:00
Glen Fernandes
d10299159a More asciidoctor changes
Reinstate the none/blank trick, but remove the blank line after it in local_shared_ptr.adoc that causes the problem. Also use that trick in place of the nested DLs which don't work with Asciidoctor 2
2019-03-24 23:41:08 -04:00
Glen Fernandes
adcab0e313 Update asciidoc to work with Asciidoctor 2.0 2019-03-24 20:28:17 -04:00
Peter Dimov
4fbb9ff076 Merge branch 'develop' 2019-03-02 21:08:43 +02:00
Glen Fernandes
8ccb36dfcf Use traits from TypeTraits 2019-02-22 19:36:32 -05:00
Glen Fernandes
fde2e91443 Use traits from TypeTraits 2019-02-22 19:01:55 -05:00
Peter Dimov
aa1341a6a2 Add BOOST_SP_NOEXCEPT to sp_counted_base_nt.hpp 2019-01-28 21:24:09 +02:00
Peter Dimov
053779f3ee Add BOOST_SP_NOEXCEPT to sp_counted_base_clang.hpp 2019-01-28 20:52:28 +02:00
Peter Dimov
51d8167fbf Add more BOOST_SP_NOEXCEPT 2019-01-28 18:46:39 +02:00
Peter Dimov
5f95fe9848 Fix .travis.yml 2019-01-06 04:37:59 +02:00
Peter Dimov
599d0bbba9 Add test/cmake_subdir_test 2019-01-05 19:43:22 +02:00
Peter Dimov
f769217ca8 Update CMakeLists.txt 2019-01-04 19:40:30 +02:00
Mike Dev
5d5d28a92e [CMake] Generate cmake target that other libraries can use
... to express their dependency on this library and retrieve any
configuration information such as the include directory and
transitive dependencies.
2019-01-02 22:32:38 +01:00
Peter Dimov
85fd341402 Merge pull request #59 from Kojoley/patch-1
Do not include the whole Predef for a single macro
2018-12-29 02:24:02 +02:00
Nikita Kniazev
eac6411867 Do not include the whole Predef for a single macro 2018-12-28 03:03:02 +03:00
Peter Dimov
97ef7970e8 Remove VARIANT from .travis.yml 2018-12-23 16:44:03 +02:00
Peter Dimov
4baa21dd5e Add libstdc++-5 for clang 7-ubsan 2018-12-23 08:17:32 +02:00
Peter Dimov
d0a89a81f0 More g++ warning suppression 2018-12-23 06:21:55 +02:00
Peter Dimov
ab2b977e4a Update clang-5 ubsan to clang-7 2018-12-23 05:19:07 +02:00
Peter Dimov
f380d4466c Avoid some g++ warnings in shared_ptr_test 2018-12-23 05:06:24 +02:00
Peter Dimov
2932ca4203 Change sp_counted_base_nt/_pt to use boost::int_least32_t instead of long (which may be 64 bit) 2018-12-23 01:54:36 +02:00
Peter Dimov
660d26c2c3 Change 03/11 to 98/0x for gcc 4.4 2018-12-23 00:08:32 +02:00
Peter Dimov
a095084492 Improve abi_test 2018-12-23 00:06:13 +02:00
Peter Dimov
a314765b94 Test variant=debug,release on Travis 2018-12-22 23:52:07 +02:00
Peter Dimov
02eba55685 Add abi_test 2018-12-22 22:56:20 +02:00
Peter Dimov
9c2c991291 Update .yml files 2018-12-18 21:53:58 +02:00
Peter Dimov
2e57ddb953 Update documentation of intrusive_ptr (document move ops, fix op<) 2018-11-25 17:54:51 +02:00
Peter Dimov
f6c3508aee Add make_local_shared_const_test 2018-11-10 21:04:22 +02:00
Peter Dimov
b7cca00408 Add make_shared_const_test 2018-11-10 20:44:00 +02:00
Peter Dimov
7e50abb9ec Merge pull request #55 from Romain-Geissler-1A/noexcept
Use BOOST_NOEXCEPT_OR_NOTHROW in public headers to prepare for C++20.
2018-11-10 19:32:01 +02:00
Peter Dimov
e7360779b0 Add g++ 8, clang 6.0, 7 to Travis 2018-11-10 18:35:29 +02:00
Romain Geissler
456da93897 Use BOOST_NOEXCEPT_OR_NOTHROW in public headers to prepare for C++20. 2018-11-09 14:55:34 +00:00
Peter Dimov
04f0847af4 Add --depth 1 to Appveyor 2018-09-21 20:53:27 +03:00
Glen Fernandes
29a08cdff6 Use BOOST_SYMBOL_VISIBLE with local_counted_base and children 2018-09-19 13:50:13 -04:00
Peter Dimov
6d3af760f6 Generously dispense BOOST_SYMBOL_VISIBLE 2018-09-18 03:18:23 +03:00
Peter Dimov
a9f39d2b94 Test make_shared/allocate_shared in dll_test too 2018-09-17 22:04:27 +03:00
Peter Dimov
4e2f236116 Add dll_test (to check for visibility issues) 2018-09-17 21:50:47 +03:00
Peter Dimov
4eb53db537 Use intrin.h under clang-cl 2018-08-12 01:26:59 +03:00
Glen Fernandes
a2b6ba85f3 Simplify exception safety in array construct utilities 2018-08-01 08:45:10 -04:00
Peter Dimov
e37cd4154f Work around ld: unrecognized option '--push-state--no-as-needed' 2018-05-10 16:16:08 +03:00
Peter Dimov
8563fc5c4e Add tests that include <windows.h> 2018-03-11 23:00:50 +02:00
Peter Dimov
67fab5c9ec Clang x64 warns that __stdcall is ignored, so don't use it there 2018-03-08 06:53:28 +02:00
Peter Dimov
f16fbdce26 Fix sp_interlocked on Cygwin 64 2018-03-08 05:15:49 +02:00
Peter Dimov
c3b3835a58 Mingw doesn't have _RTL_CRITICAL_SECTION 2018-03-08 03:34:00 +02:00
Peter Dimov
d1600b8abc Do not define pthread_* in lightweight_thread.hpp; mingw-w64 includes pthread.h in the standard library headers 2018-03-08 01:19:44 +02:00
Peter Dimov
5885763287 Remove clang from Appveyor; doesn't really work. 2018-03-08 00:39:15 +02:00
Peter Dimov
9bb12692b3 Only test C++14 with clang on Appveyor 2018-03-07 21:23:01 +02:00
Peter Dimov
773ef80f5d Add mingw configurations; move LLVM clang in its own VS2017 job 2018-03-07 20:06:04 +02:00
Peter Dimov
704de2bd67 Add Cygwin to Appveyor 2018-03-07 18:27:45 +02:00
Peter Dimov
1caa233faa Add address-model=32,64 to Appveyor 2018-03-07 17:37:28 +02:00
Peter Dimov
605d4a2789 Merge pull request #49 from joaquintides/patch-1
fixed AppVeyor link
2018-03-05 16:28:17 +02:00
joaquintides
6ab9b93088 fixed AppVeyor link 2018-03-05 15:13:18 +01:00
Peter Dimov
4129bb6a5c Use unique_ptr instead of auto_ptr when available 2018-02-19 06:16:11 +02:00
Peter Dimov
3b64e5ecb3 Add lw_thread_test 2018-02-19 02:02:31 +02:00
Peter Dimov
4025698fe8 Change atomic operations to take an arbitrary MemoryOrder type, to fix test breakage caused by transition to scoped enum in Boost.Atomic, tracking C++20 2018-02-07 17:45:07 +02:00
Peter Dimov
2d7ab197a7 Remove variant=debug,release from Travis; too weak, too slow 2018-01-24 15:16:32 +02:00
Peter Dimov
5877b08490 Disable spinlock_pool_test on msvc-9.0/release as well 2018-01-23 21:49:30 +02:00
Peter Dimov
ffe5b46f75 Silence MS warning about strcpy 2018-01-23 21:45:59 +02:00
Peter Dimov
4abc74fe28 Disable spinlock_pool_test on msvc-8.0/release 2018-01-23 19:05:44 +02:00
Peter Dimov
12a646c607 Update .travis.yml, appveyor.yml 2018-01-23 19:02:35 +02:00
Peter Dimov
937a3e0e93 Remove tabs 2018-01-23 06:29:17 +02:00
Peter Dimov
258fa75a7e Add -fsanitize=undefined to Travis 2018-01-20 02:20:35 +02:00
Peter Dimov
93d0d69f5e Add clang-3.3, 3.4 to Travis 2018-01-19 19:43:30 +02:00
Peter Dimov
f173f9c0fb Remove -fno-deduce-init-list from make_shared_arrays_test, allocate_shared_arrays_test; seems no longer needed 2018-01-18 14:36:58 +02:00
Peter Dimov
6a5942f55f Fix make_unique_value_test line 2018-01-18 14:35:15 +02:00
Peter Dimov
293a4ee009 Use full gcc-4.4.7 version 2018-01-18 14:34:06 +02:00
Peter Dimov
8e3aa3a565 make_unique_value_test: add -fno-deduce-init-list for gcc-4.6 2018-01-18 00:13:00 +02:00
Peter Dimov
78bebd5166 Disable auto_ptr_lv_fail on g++ 4.4 (known failure) 2018-01-17 21:17:19 +02:00
Peter Dimov
a47cf35b0f Disable atomic_sp_constexpr_test on libc++ 5.0 as well 2018-01-17 19:17:17 +02:00
Peter Dimov
8d0afb670f atomic_sp_constexpr_test: add pragma messages when skipped 2018-01-17 16:46:54 +02:00
Peter Dimov
77a35856c6 Add g++ 4.4, 4.6 to Travis 2018-01-16 18:50:09 +02:00
Peter Dimov
693109361e Add missing cxxstd=03 to libc++ Travis job 2018-01-16 16:13:41 +02:00
Peter Dimov
6735806863 Add clang++-libc++ to Travis 2018-01-16 16:09:13 +02:00
Peter Dimov
b0dc300154 Merge pull request #47 from wzssyqa/mips-r6-no-set-mips2
disable .set mips2 for mips release r6
2018-01-03 07:18:59 +02:00
Peter Dimov
adc998469a Add container_hash to Travis and Appveyor 2018-01-03 02:59:19 +02:00
YunQiang Su
4252ed31de disable .set mips2 for mips release r6
MIPS r6 changed the encoding for `ll' instruction,
if we `.set mips2', it will generate the old encoding for `ll'.

So here we disable it for r6.
2017-12-31 14:14:11 +08:00
Peter Dimov
279372a784 Merge branch 'develop' 2017-12-18 17:26:13 +02:00
Peter Dimov
b77b7cfd62 Fix intrusive_ptr converting constructor doc issue #46 2017-11-28 20:13:32 +02:00
Peter Dimov
2553a71b79 Fix intrusive_ptr converting constructor doc issue #46 2017-11-28 20:09:52 +02:00
Glen Fernandes
5dfcd2a6e4 Rename parameters to cope with gcc 4.8 -Wshadow 2017-11-27 23:47:13 -05:00
Peter Dimov
6f30b395e4 Add -j 3 to Travis 2017-11-06 05:29:33 +02:00
Peter Dimov
014318a1ba Reduce Appveyor jobs 2017-11-06 02:34:46 +02:00
Peter Dimov
d2c8eea08d Add VS2017 /std:c++17 to Appveyor 2017-11-06 01:49:20 +02:00
Glen Fernandes
4e0d47302b Merge pull request #45 from glywk/contribution
Fix make_unique header filename documentation
2017-11-02 21:46:41 -04:00
glywk
765840cd71 Fix make_unique header filename documentation 2017-11-02 23:07:16 +01:00
Glen Fernandes
cb4a878fa8 Merge pull request #44 from glenfe/develop
sp_array_construct condition for trivial should include has_trivial_destructor
2017-11-02 13:02:05 -04:00
Glen Fernandes
57a585ed46 sp_array_construct condition for trivial should include has_trivial_destructor 2017-11-02 11:53:41 -04:00
Peter Dimov
949338ff18 Add test that verifies no temporaries are created by array make_shared 2017-11-02 17:45:17 +02:00
Peter Dimov
50fbbe91d8 Re-add libstdc++-4.9-dev to clang 3.5, 3.8, 3.9 2017-10-25 00:30:48 +03:00
Peter Dimov
e88227b506 Update .travis.yml 2017-10-24 20:20:15 +03:00
Rene Rivera
410f2ce8d4 Remove redundant local asciidoctor tool spec. 2017-10-22 07:56:41 -05:00
Peter Dimov
4e2e758f58 Merge pull request #42 from grafikrobot/patch-1
Guard against redef of asciidoctor in common b2.
2017-10-19 03:02:10 +03:00
Rene Rivera
9cb8ee086f Guard against redef of asciidoctor in common b2. 2017-10-18 18:43:56 -05:00
Peter Dimov
a054a570c1 Add quick test target 2017-09-04 15:45:07 +03:00
Peter Dimov
219dc523ec Install libstdc++-4.9 for clang 3.5, 3.8, 3.9 in .travis.yml 2017-09-01 23:19:03 +03:00
Peter Dimov
5da882293d Merge branch 'develop' 2017-09-01 16:15:33 +03:00
Peter Dimov
868a870a59 Fix lightweight_mutex w/ BOOST_USE_WINDOWS_H 2017-09-01 13:25:19 +03:00
Peter Dimov
10c6233029 Merge branch 'develop' 2017-08-29 00:44:14 +03:00
Peter Dimov
bcfe1be681 Merge pull request #40 from BenjaminW3/topic-fix-nvcc
fix compilation for nvcc+clang
2017-08-28 10:51:22 +03:00
Benjamin Worpitz
966786e7f9 fix compilation for nvcc+clang
nvcc seems to use the host compiler for preprocessing the source for the device and host compilation.
When compiling the host code with the host compiler (clang), `__builtin_assume` is detected correctly and is also available during compilation.
When compiling the device code with nvcc, this builtin function is not available.
2017-08-28 08:12:48 +02:00
Peter Dimov
087471a232 Bump msvc version checks from <= 1910 to < 1920 2017-08-23 09:16:35 +03:00
Peter Dimov
06bd43d5b5 Merge branch 'develop' 2017-07-13 16:36:43 +03:00
Glen Fernandes
1758d44e4c Add basic synopsis and description for make_local_shared 2017-07-08 08:50:59 -04:00
Peter Dimov
1c13ec0888 Remove wrong doc link from meta/libraries.json 2017-07-07 17:58:49 +03:00
Peter Dimov
cc7eb56f51 Fixed broken link in techniques.adoc 2017-07-07 14:14:54 +03:00
Peter Dimov
eb64ae8daa Untabify pointer_cast_test2 2017-07-07 00:59:01 +03:00
Glen Fernandes
a3c8c2125a Use has_trivial_assign in construction utilities 2017-07-04 13:45:56 -04:00
Glen Fernandes
3aa419463c Simplify lsp state types 2017-07-01 10:00:47 -04:00
Glen Fernandes
e4ba116d7e Minor refactoring in allocate_shared implementations 2017-06-29 22:33:43 -04:00
Glen Fernandes
864a0c80dd Conditionally compile allocate_local_shared tests 2017-06-29 13:33:14 -04:00
Glen Fernandes
be736e5088 Implement allocate_local_shared for arrays
Also fix the local_shared_ptr constructor to use element_type
2017-06-29 13:05:03 -04:00
Glen Fernandes
48294c483f Use new shared_count constructors in allocate_shared 2017-06-29 09:24:02 -04:00
Peter Dimov
13e73d6a78 Do not use UINT_MAX to avoid -Wmicrosoft-enum-value from Clang 2017-06-27 16:23:18 +03:00
Peter Dimov
20a517cc3d Clang/C2 doesn't have _mm_pause 2017-06-27 15:41:56 +03:00
Peter Dimov
65d412c840 Execute bootstrap in subshell on Appveyor to preserve TOOLSET 2017-06-22 17:34:20 +03:00
Peter Dimov
d031d4719f Check use counts in make_local_shared tests 2017-06-22 15:39:46 +03:00
Peter Dimov
c1979bcaf5 Check use counts in make_shared tests 2017-06-22 15:31:50 +03:00
Peter Dimov
0adb1fb212 Add shared_count constructor taking sp_counted_base* 2017-06-22 15:24:49 +03:00
Peter Dimov
7410cb1733 Update history.adoc. 2017-06-21 20:25:37 +03:00
Peter Dimov
2d087d0003 Do not use A::destroy in allocate_shared_noinit 2017-06-21 13:44:17 +03:00
Peter Dimov
ca7a01a593 Add more tests. Update Jamfile to new style. 2017-06-21 04:07:17 +03:00
Peter Dimov
314a6634d4 Merge branch 'feature/local_shared_ptr' into develop 2017-06-21 03:33:00 +03:00
Glen Fernandes
6cbc1e6775 Update allocate_shared array unit tests
Tests that do not always use allocator bound for element_type.
2017-06-20 20:06:59 -04:00
Peter Dimov
81e1cfe301 Merge branch 'develop' into feature/local_shared_ptr 2017-06-21 03:04:16 +03:00
Peter Dimov
eb8aa36854 Merge branch 'develop' of https://github.com/boostorg/smart_ptr into develop 2017-06-21 03:03:21 +03:00
Peter Dimov
e210c5728d Add local_shared_ptr.adoc 2017-06-21 03:02:48 +03:00
Glen Fernandes
4046186a2d Use BOOST_NOEXCEPT_OR_NOTHROW for get_deleter
throw() optimizes better there with older versions of GCC in C++98.
2017-06-20 19:27:58 -04:00
Peter Dimov
01b73a8bfa Merge branch 'develop' into feature/local_shared_ptr 2017-06-21 02:07:27 +03:00
Peter Dimov
c85abde6b0 Update shared_ptr.adoc 2017-06-21 02:06:16 +03:00
Peter Dimov
e9523962ae Update .travis.yml 2017-06-21 01:20:11 +03:00
Peter Dimov
4e5d067ba8 Add local_sp_fn_test 2017-06-20 22:26:07 +03:00
Peter Dimov
827206ec57 Merge branch 'develop' into feature/local_shared_ptr 2017-06-20 22:07:53 +03:00
Peter Dimov
0cdad6421d Add shared_ptr_fn_test 2017-06-20 22:07:12 +03:00
Peter Dimov
f7f7e0183d Merge branch 'feature/local_get_deleter' into feature/local_shared_ptr 2017-06-20 21:38:44 +03:00
Peter Dimov
f901988e57 Store shared_count in local_counted_base, not shared_ptr 2017-06-20 21:38:03 +03:00
Peter Dimov
22d150a1a9 Merge branch 'feature/local_get_deleter' into feature/local_shared_ptr 2017-06-20 20:39:04 +03:00
Peter Dimov
fb17bf685e Add more tests; fix errors 2017-06-20 20:38:26 +03:00
Peter Dimov
052ebd1946 Merge branch 'develop' into feature/local_get_deleter 2017-06-20 19:35:23 +03:00
Peter Dimov
028bb2cee8 Fix get_deleter in allocate_shared_array.hpp 2017-06-20 19:33:39 +03:00
Peter Dimov
9fe6885078 Add more get_deleter tests 2017-06-20 19:18:30 +03:00
Peter Dimov
6e5a382b6b Start work on get_deleter for local_shared_ptr 2017-06-20 19:01:16 +03:00
Peter Dimov
87272703c2 Add get_deleter test with an incomplete class 2017-06-20 17:47:59 +03:00
Peter Dimov
1c097b5764 Add get_deleter test with an incomplete class 2017-06-20 17:47:17 +03:00
Peter Dimov
014181e1f9 Merge branch 'develop' into feature/local_shared_ptr 2017-06-20 06:25:56 +03:00
Peter Dimov
0b9547ddad Disable atomic_sp_constexpr_test on libc++ 2017-06-20 06:25:27 +03:00
Peter Dimov
b104d85d95 Fix use of allocator_traits 2017-06-20 05:36:47 +03:00
Peter Dimov
e92d79c0a6 Add 14/1z to clang 3.5, 3.6, 3.7 2017-06-20 04:31:35 +03:00
Peter Dimov
2b5869882a Optimize make_local_shared to use a single allocation 2017-06-20 04:27:45 +03:00
Peter Dimov
1f86907a3d Add more tests 2017-06-20 02:00:19 +03:00
Peter Dimov
685b40cc1b Merge branch 'develop' into feature/local_shared_ptr 2017-06-20 01:49:04 +03:00
Peter Dimov
dcfb8489c6 Fix mistakes in atomic_sp_constexpr_test 2017-06-20 01:48:28 +03:00
Peter Dimov
6218c52c1a Add make_local_shared 2017-06-20 01:42:45 +03:00
Peter Dimov
c2b6e96cd7 Merge branch 'develop' into feature/local_shared_ptr 2017-06-19 20:39:29 +03:00
Peter Dimov
b062d84d36 Update history.adoc 2017-06-19 20:38:51 +03:00
Peter Dimov
68fb786d4d Add more tests 2017-06-19 17:36:13 +03:00
Peter Dimov
f7275b7f45 Add more tests 2017-06-19 02:30:54 +03:00
Peter Dimov
edf02ab0f9 Add more tests 2017-06-19 01:05:01 +03:00
Peter Dimov
5b316e6e90 Update specification of atomic_shared_ptr 2017-06-18 15:34:57 +03:00
Peter Dimov
7ed8583a9c Document shared_ptr atomic access functions 2017-06-18 15:24:00 +03:00
Peter Dimov
6474847481 Make atomic_shared_ptr's default constructor constexpr 2017-06-18 07:56:42 +03:00
Peter Dimov
75003f734f Merge branch 'feature/constexpr' into develop 2017-06-18 07:11:49 +03:00
Peter Dimov
79e6fcdd61 Remove comment; C++11 does not guarantee this static init 2017-06-18 05:00:42 +03:00
Peter Dimov
4341446e04 #ifdef constexpr tests on msvc and clang c++11 2017-06-18 04:21:22 +03:00
Peter Dimov
9c18322e85 Fix appveyor.yml again 2017-06-18 03:55:48 +03:00
Peter Dimov
49095c3236 Fix appveyor.yml 2017-06-18 03:36:49 +03:00
Peter Dimov
fff61ab5d6 Add clang 3.5 to ravis 2017-06-18 03:35:12 +03:00
Peter Dimov
aef27128f2 Add feature branch testing, matrix to Appveyor 2017-06-18 03:32:32 +03:00
Peter Dimov
c1d72af0a4 Add g++ 7, clang++ 4 to Travis 2017-06-18 03:11:59 +03:00
Peter Dimov
0e78e219f5 Make default constructors constexpr 2017-06-18 02:43:20 +03:00
Peter Dimov
2e469dd7f3 Fix .travis.yml 2017-06-18 02:20:00 +03:00
Peter Dimov
d9296befa8 Fix branch regexp in .travis.yml 2017-06-18 00:47:58 +03:00
Peter Dimov
f321ce404f Enable Travis on feature branches 2017-06-18 00:08:05 +03:00
Peter Dimov
67d897a533 Add a spinlock to atomic_shared_ptr 2017-06-17 23:37:18 +03:00
Peter Dimov
e462f17c2d Merge branch 'feature/local_shared_ptr' into develop 2017-06-17 21:26:13 +03:00
Peter Dimov
b8390aeffb Add more tests 2017-06-17 21:24:07 +03:00
Peter Dimov
9dafc01024 Merge branch 'develop' into feature/local_shared_ptr 2017-06-17 01:36:17 +03:00
Peter Dimov
7d51c868eb Add more tests 2017-06-17 01:34:58 +03:00
Glen Fernandes
0b0b7af05b Fix intrusive_ref_counter.adoc 2017-06-16 18:18:25 -04:00
Peter Dimov
7bd389c95e Merge branch 'develop' into feature/local_shared_ptr 2017-06-17 00:15:39 +03:00
Peter Dimov
1cae5c5696 Fix documentation links in headers 2017-06-17 00:13:21 +03:00
Peter Dimov
369fdbe38d Merge branch 'develop' into feature/local_shared_ptr 2017-06-16 20:20:54 +03:00
Peter Dimov
43b37d4f28 Merge branch 'feature/atomic_shared_ptr' into develop 2017-06-16 20:20:17 +03:00
Peter Dimov
a048cfb56d Minor fixes to atomic_shared_ptr.hpp 2017-06-16 20:19:37 +03:00
Peter Dimov
070a3a9f1a Add atomic_shared_ptr.adoc 2017-06-16 20:15:23 +03:00
Peter Dimov
d03ef3db5c Merge branch 'develop' into feature/local_shared_ptr 2017-06-16 19:42:45 +03:00
Peter Dimov
6d97c2b89e Remove javascript that tried to integrate the Boost banner, as it didn't work 2017-06-16 19:32:35 +03:00
Peter Dimov
7484d4da41 Merge branch 'develop' into feature/local_shared_ptr 2017-06-16 18:40:01 +03:00
Peter Dimov
2964ed2379 Merge branch 'feature/atomic_shared_ptr' into develop 2017-06-16 18:36:10 +03:00
Peter Dimov
a7668291d2 Add atomic_shared_ptr 2017-06-16 18:26:17 +03:00
Peter Dimov
ffc48e63d8 Merge branch 'develop' into feature/local_shared_ptr 2017-06-16 17:18:33 +03:00
Peter Dimov
bcc9e50a54 Merge branch 'feature/asciidoc' into develop 2017-06-16 17:17:47 +03:00
Peter Dimov
8812114601 Fix line wrapping in pdf 2017-06-15 21:34:53 +03:00
Peter Dimov
5b817ba04d Fix synopses 2017-06-15 21:23:06 +03:00
Glen Fernandes
6db55f7dfd Add _add_ref and _release overload documentation 2017-06-15 11:43:40 -04:00
Glen Fernandes
61de342adc Add deprecated shared_array documentation 2017-06-15 08:16:50 -04:00
Glen Fernandes
7f760526ab Add intrusive_ref_counter documentation 2017-06-15 02:09:06 -04:00
Glen Fernandes
478a819cb5 Add generic pointer casts documentation 2017-06-15 01:36:59 -04:00
Glen Fernandes
902ca6fdf3 Remove 'see below' in documentation 2017-06-14 20:40:11 -04:00
Glen Fernandes
074882976f Slightly better looking comments in documentation 2017-06-14 11:28:41 -04:00
Glen Fernandes
c1820b4a27 Various documentation fixes 2017-06-14 10:29:24 -04:00
Glen Fernandes
8096b7d324 Add make_unique documentation 2017-06-14 08:24:31 -04:00
Glen Fernandes
bdcab9df47 Add examples to make_shared documentation 2017-06-14 01:41:49 -04:00
Glen Fernandes
8f99919102 Update make_shared documentation 2017-06-14 00:18:29 -04:00
Peter Dimov
27898b0823 Constrain conversions to shared_ptr/weak_ptr 2017-06-13 20:57:12 +03:00
Peter Dimov
47ee1e09e9 Use single allocation in deleter and allocator constructors 2017-06-13 18:29:18 +03:00
Peter Dimov
4dda1b5fbb Add lsp_array_* tests 2017-06-13 18:03:01 +03:00
Peter Dimov
585de501da Embed local_counted_base in the deleter in the pointer case 2017-06-13 17:27:06 +03:00
Peter Dimov
420626d6d9 Add weak_ptr.adoc 2017-06-13 06:34:16 +03:00
Peter Dimov
ab99c8f7aa Reflect unique_ptr constructor change 2017-06-13 05:56:19 +03:00
Peter Dimov
0eb6ad145d Merge branch 'develop' into feature/asciidoc 2017-06-13 05:51:51 +03:00
Peter Dimov
1d314c5668 Make null unique_ptr convert to empty shared_ptr 2017-06-13 05:50:40 +03:00
Peter Dimov
5b7d3c08ab Small fix to enable_shared_from_this.adoc 2017-06-13 02:51:02 +03:00
Peter Dimov
f770e53989 More history 2017-06-13 02:22:51 +03:00
Peter Dimov
c4d07defcd Add .gitignore 2017-06-13 01:46:50 +03:00
Peter Dimov
65e616c90b Add a history item for the N1450 formal proposal 2017-06-13 01:45:18 +03:00
Peter Dimov
f90b418460 Add enable_shared_from_this.adoc 2017-06-13 01:34:31 +03:00
Peter Dimov
bd2474e7f3 Add shared_ptr.adoc 2017-06-12 20:06:12 +03:00
Peter Dimov
a88d8b5b29 Add pointer_to_other.adoc 2017-06-12 18:20:54 +03:00
Peter Dimov
213c00aed7 Merge branch 'develop' into feature/asciidoc 2017-06-12 18:07:46 +03:00
Peter Dimov
52d976fde2 Use BOOST_SP_NOEXCEPT, BOOST_SP_NOEXCEPT_WITH_ASSERT 2017-06-12 18:06:54 +03:00
Peter Dimov
a6031ff8e2 Add scoped_array.adoc 2017-06-12 16:53:57 +03:00
Peter Dimov
239fe204de Merge branch 'develop' into feature/asciidoc 2017-06-12 15:54:44 +03:00
Peter Dimov
e75fa9329b Remove noexcept on ~local_counted_base for g++ 4.7 2017-06-12 15:53:16 +03:00
Peter Dimov
3b16e1cc3e Add intrusive_ptr.adoc 2017-06-12 05:17:34 +03:00
Peter Dimov
392b3c76f0 Add techniques.adoc 2017-06-12 04:06:27 +03:00
Peter Dimov
dea4e8129d Complete scoped_ptr.adoc 2017-06-12 03:12:03 +03:00
Peter Dimov
0dfb4dad0f Start rewriting documentation in asciidoc 2017-06-12 01:58:08 +03:00
Peter Dimov
aec76051f8 Merge branch 'feature/local_shared_ptr' into develop 2017-06-12 00:52:33 +03:00
Peter Dimov
8f2e6d04de Add more tests 2017-06-12 00:19:07 +03:00
Peter Dimov
8d9c4df71a Add more tests 2017-06-11 20:35:51 +03:00
Peter Dimov
b18f68324f Add more tests 2017-06-05 16:38:41 +03:00
Peter Dimov
aeadd6aeff Initial commit of local_shared_ptr 2017-06-04 21:24:20 +03:00
Peter Dimov
3c47079f4d Merge branch 'develop' 2017-06-04 19:08:05 +03:00
Peter Dimov
ca9cb71e86 Merge pull request #39 from Teemperor/ReencodeAsUtf8
Reencoded a few headers that used Windows-1252 with UTF-8.
2017-06-02 23:08:35 +03:00
Raphael Isemann
ba98b8c33f Reencoded a few headers that used Windows-1252 with UTF-8.
Nearly every header in the boost codebase is UTF-8, but here there
are a few headers which are using Windows-1252, which makes it impossible
for some tools to parse those files. This patch just reencodes them
with UTF-8 like the rest of the codebase. I checked that the name of the
author is still correct after this change.

No functional change intended.
2017-06-02 14:51:53 +02:00
Peter Dimov
3160cbb2e3 Merge branch 'master' of https://github.com/boostorg/smart_ptr 2017-06-01 03:28:39 +03:00
Peter Dimov
bfa3752ad7 Merge branch 'develop' 2017-06-01 03:28:21 +03:00
Peter Dimov
e9010baaf5 Merge branch 'Belcourt-develop' into develop 2017-05-27 03:02:32 +03:00
Peter Dimov
b530ffcae5 Remove redundant check; add coment; include config.hpp 2017-05-27 03:01:34 +03:00
K. Noel Belcourt
7f42d987e7 Protect clang pragmas with BOOST_CLANG macro. 2017-05-26 12:33:59 -06:00
Glen Fernandes
469015992a Merge branch 'develop' 2017-05-02 08:57:13 -04:00
Glen Fernandes
33b18c7da0 Reformat (line wrap at 80 characters) 2017-05-02 08:12:25 -04:00
Peter Dimov
596adfc69a Merge branch 'develop' 2017-05-01 13:50:49 +03:00
Glen Fernandes
e99e722fa5 Add alternative sp_array_construct for trivially destructible case 2017-04-30 19:20:57 -04:00
Peter Dimov
7ef8fa4a19 Fix lwm_win32_cs.hpp for Clang 2017-04-24 19:53:24 +03:00
Peter Dimov
9081dc5573 Add lwm_win32_cs_test 2017-04-24 19:52:57 +03:00
Peter Dimov
0043228495 Add clang-3.9/linux, c++1z/osx to Travis 2017-04-24 19:52:37 +03:00
Glen Fernandes
6bdd3fde65 Add alternative sp_array_construct for trivially destructible case 2017-04-23 01:42:15 -04:00
Peter Dimov
3568e093bb Fix lwm_win32_cs.hpp for Clang 2017-04-16 21:38:29 +03:00
Peter Dimov
acb29ad6f3 Add lwm_win32_cs_test 2017-04-16 21:02:07 +03:00
Peter Dimov
d2c1ed0ed5 Add clang-3.9/linux, c++1z/osx to Travis 2017-04-16 00:18:24 +03:00
Glen Fernandes
0085752a56 Merge branch 'develop' 2017-03-13 19:19:40 -04:00
Peter Dimov
d7ad42724d Revert Appveyor changes. 2017-03-13 19:42:39 +02:00
Peter Dimov
83d3f07b0d Fourth try to obtain bootstrap.log from Appveyor 2017-03-13 19:02:57 +02:00
Peter Dimov
994f39f9b0 Third try to obtain bootstrap.log from Appveyor 2017-03-13 18:47:38 +02:00
Peter Dimov
f45dd4d955 Second try to obtain bootstrap.log from Appveyor 2017-03-13 18:36:52 +02:00
Peter Dimov
b4abcdb016 Try to obtain bootstrap.log from Appveyor 2017-03-13 18:29:04 +02:00
Glen Fernandes
25cf644f60 Merge pull request #37 from glenfe/develop
Add examples back to documentation
2017-03-13 11:22:06 -04:00
Glen Fernandes
71ef7850ab Add examples back to documentation 2017-03-13 10:59:58 -04:00
Glen Fernandes
40c0ddcbd6 Merge pull request #36 from boostorg/develop
Merge documentation changes
2017-03-10 13:32:44 -05:00
Glen Fernandes
687d31b7c8 Update documentation in make_unique.html 2017-03-10 11:55:06 -05:00
Glen Fernandes
fac6fbe3cf Update documentation in make_shared_array.html 2017-03-10 10:21:21 -05:00
Glen Fernandes
d3b9ee7d24 Merge branch 'develop' 2017-03-06 08:59:03 -05:00
Glen Fernandes
650537da60 Update unit tests for make_unique 2017-03-06 08:36:57 -05:00
Glen Fernandes
324347b9ec Update unit tests for shared array functions 2017-03-06 01:18:16 -05:00
Glen Fernandes
79e675c727 Merge branch 'develop' 2017-03-05 22:09:34 -05:00
Glen Fernandes
6ef791c715 Rename identifiers in allocate and deallocate 2017-03-05 22:07:58 -05:00
Glen Fernandes
15ed558a29 Further simplify alignment logic in allocate 2017-03-05 21:39:22 -05:00
Glen Fernandes
106ada7770 Remove unnecessary helper function 2017-03-05 19:13:26 -05:00
Glen Fernandes
9f70f6619f Do not rely on size of type_with_alignment 2017-03-05 19:10:56 -05:00
Glen Fernandes
494c0cd2c0 Merge branch 'develop' 2017-03-04 23:43:49 -05:00
Glen Fernandes
8c058dfeee Use BOOST_NOEXCEPT_OR_NOTHROW over BOOST_NOEXCEPT 2017-03-04 23:36:24 -05:00
Glen Fernandes
0807efa91a Merge branch 'develop' 2017-03-04 01:09:35 -05:00
Glen Fernandes
bea0fc4a37 Update make_shared_array documentation 2017-03-04 01:07:43 -05:00
Glen Fernandes
3f21bac34f Merge pull request #35 from boostorg/develop
Merge develop
2017-03-03 13:23:35 -05:00
Peter Dimov
7beb91fd0e Merge branch 'glenfe-allocate_shared' into develop 2017-03-02 06:06:35 +02:00
Glen Fernandes
d1bb87d34e Remove the now unnecessary allocate hint parameter 2017-03-01 13:15:23 -05:00
Glen Fernandes
7570340d70 Add test for allocator construct usage 2017-03-01 13:03:14 -05:00
Glen Fernandes
b42acf77b3 Only use allocator construct/destroy for value_type, not shared_count 2017-03-01 06:18:06 -05:00
Peter Dimov
1f9c63c34f Fix MSVC parsing problem in allocate_shared_array 2017-03-01 12:08:17 +02:00
Peter Dimov
f8524c42a8 Add test for a MSVC parsing problem in make_shared 2017-03-01 12:02:30 +02:00
Glen Fernandes
52fbf70879 Special case aligning up sizes and change integral constant style 2017-02-28 19:23:02 -05:00
Glen Fernandes
fb59cd574e Copy rebind allocator before impl destruct 2017-02-28 07:21:49 -05:00
Glen Fernandes
c749052162 Merge pull request #33 from glenfe/allocate_shared_array
Revise make_shared and allocate_shared for arrays
2017-02-28 04:26:20 -05:00
Glen Fernandes
970e88897c Revise make_shared and allocate_shared for arrays 2017-02-28 03:47:09 -05:00
Peter Dimov
609de5d711 Merge branch 'develop' 2017-02-25 19:30:08 +02:00
Peter Dimov
d641b9c436 Merge pull request #32 from pgroke-dt/z_OS_XL_C++_support
don't define BOOST_SP_HAS_SYNC for z/OS XL C/C++ compiler
2017-02-25 13:38:33 +02:00
Paul Groke
3bb4e4d2df don't define BOOST_SP_HAS_SYNC for z/OS XL C/C++ compiler 2017-02-25 05:44:04 +01:00
Peter Dimov
5ab9a77d50 Merge branch 'develop'
Conflicts:
	.travis.yml
2017-02-16 15:37:26 +02:00
Peter Dimov
b80ffbeb3d Remove tools/inspect from appveyor.yml 2017-02-16 15:35:53 +02:00
Peter Dimov
5f8c2a7ee0 Remove tools/inspect from .travis.yml 2017-02-16 15:34:51 +02:00
Peter Dimov
94634cb853 Only install necessary packages in .travis.yml to speed it up 2017-02-07 01:50:59 +02:00
Peter Dimov
17a07a228e Add platform matrix to .travis.yml 2017-02-06 21:32:51 +02:00
Peter Dimov
d4bc4c9733 Add platform matrix to .travis.yml 2017-02-06 16:51:33 +02:00
Peter Dimov
1d7f6b9bfd Merge pull request #31 from gongminmin/ClangC2
Fix compiling problems under ClangC2.
2017-02-06 15:26:24 +02:00
Minmin Gong
d718d21d6b Fix compiling problems under ClangC2. 2017-02-05 15:51:42 -08:00
Peter Dimov
39b14fa0d6 Merge branch 'develop' 2017-01-01 04:10:26 +02:00
Peter Dimov
19147212a9 Merge pull request #29 from cdglove/rvalue_casts
Add rvalue versions of static_pointer_cast, const_pointer_cast, dynamic_pointer_cast, reinterpret_pointer_cast.
2016-12-12 05:45:17 +02:00
Peter Dimov
53928bcc12 Merge pull request #30 from cdglove/reinterpret_pointer_cast_test
Add explicit tests for reinterpret_pointer_cast
2016-12-12 05:42:29 +02:00
Chris Glover
9e568dad6e Add explicit tests for reinterpret_pointer_cast. Based on existing pointer_cast tests in shared_ptr_test.cpp 2016-12-11 22:18:57 -05:00
Chris Glover
ebd1788f2c Add test for rvalue reinterpret_pointer_cast. 2016-12-11 21:18:18 -05:00
Chris Glover
3e2ac10e94 Add rvalue versions of static_pointer_cast, const_pointer_cast, dynamic_pointer_cast, reinterpret_pointer_cast.
Aligns with proposed addition to std:: here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0390r0.htm
2016-12-11 15:38:34 -05:00
Peter Dimov
61075bb9df Move extra files to extras/ as the src/ and test/ directories are scanned for dependencies 2016-11-10 15:04:21 +02:00
Peter Dimov
3e61a63f60 Use throw() in place of noexcept on msvc-11.0,12.0 for the standard nothrow traits 2016-11-08 18:42:51 +02:00
Peter Dimov
a7fbb0a841 Do not use components removed in C++17 (auto_ptr, binary_function) 2016-11-06 15:35:46 +02:00
Peter Dimov
1e9e2ed6aa Merge branch 'develop' 2016-09-30 16:06:15 +03:00
Peter Dimov
bdc19dee01 Merge branch 'feature/unique_ptr_casts' into develop 2016-09-10 21:09:05 +03:00
Peter Dimov
3aa720714d Update documentation. 2016-09-10 20:57:35 +03:00
Peter Dimov
94a04e57fb Merge branch 'develop' into feature/unique_ptr_casts 2016-09-10 20:28:14 +03:00
Peter Dimov
776b33ec09 Merge pull request #26 from muggenhor/make_shared-constructor-forwarding
Add test for make_shared's move-emulation support
2016-09-10 20:27:12 +03:00
Peter Dimov
5595622c3e Relax dynamic_cast check; rephrase const_cast test to be more MSVC-friendly. 2016-09-10 20:18:37 +03:00
Peter Dimov
2ae3e4ba44 Remove static_pointer_cast restriction; test dynamic cross cast. 2016-09-10 20:07:47 +03:00
Giel van Schijndel
b5498d944e Add test for make_shared's move-emulation support
This tests the functionality added with PR boostorg/smart_ptr#24.

Specifically this tests that passing moveable-only types to
constructors is possible through make_shared. Note that real rvalue's
still cannot be passed that way on C++03 unfortunately because there's
no generic way of accomplishing that with current move emulation.
2016-09-10 18:38:37 +02:00
Peter Dimov
8fac3c9f2f Add one more dynamic_cast test, fold back _test3 into test2. 2016-09-10 19:15:47 +03:00
Peter Dimov
a14515a364 Add negative pointer cast tests. 2016-09-10 18:43:22 +03:00
Peter Dimov
190c06e25d Add tests for unique_ptr casts. 2016-09-10 17:55:14 +03:00
Peter Dimov
62a8a9d6cc Merge branch 'karo/unique_ptr_casts' of https://github.com/koraa/smart_ptr into feature/unique_ptr_casts 2016-09-10 14:48:26 +03:00
Peter Dimov
48401806f4 Merge branch 'make_shared-constructor-forwarding' of https://github.com/muggenhor/boost-smart_ptr into develop 2016-09-10 14:24:52 +03:00
Peter Dimov
02de302774 Merge branch 'suppress-weak-vtables-warning' of https://github.com/Kojoley/smart_ptr into develop 2016-09-10 13:55:20 +03:00
Peter Dimov
80597b379e Copy repo instead of doing a checkout, for pull requests. 2016-09-10 13:47:05 +03:00
Peter Dimov
840e9fc96e Apply MIPS16 patch from ticket #12418 2016-09-02 20:13:15 +03:00
Nikita Kniazev
70367e848e Suppress weak vtables warnings 2016-08-31 17:32:09 +03:00
Peter Dimov
e8daeaee1c Enable Travis notifications on success 2016-08-28 22:37:10 +03:00
Peter Dimov
3b9ae9fd5f Switch from msvc-12.0 to msvc-14.0 on Appveyor 2016-08-28 22:01:59 +03:00
Peter Dimov
20fedcff2c Use <atomic> by default when BOOST_NO_CXX11_HDR_ATOMIC is not defined 2016-08-28 21:28:21 +03:00
Giel van Schijndel
de38a735ea boost::make_shared: use Constructor Forwarding on C++03
Use Boost.Move's move emulation and documented Constructor Forwarding
technique to provide (partial) constructor forwarding on compilers that
don't support r-value references.

This allows constructing types taking movable-but-not-copyable types as
constructor arguments. Additionally it's generally more efficient for
movable-and-copyable types, but that's just a nice-to-have.
2016-07-25 15:02:57 +02:00
Karolin Varner
ce52fb1045 pointer_casts with move semantics for unique_ptr 2016-06-06 16:08:26 +02:00
Karolin Varner
6b787f1cec Add overloads for std::shared_ptr to pointer casts 2016-06-06 14:51:44 +02:00
Karolin Varner
2185c4f005 Fix a documentation typo 2016-06-05 23:32:45 +02:00
Karolin Varner
6d5f554baa Reuse code for plain and shared in ptr cast tests 2016-06-05 23:32:45 +02:00
318 changed files with 25188 additions and 7961 deletions

View File

@@ -1,4 +1,4 @@
# Copyright 2016 Peter Dimov
# Copyright 2016-2019 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
@@ -6,43 +6,362 @@ language: cpp
sudo: false
os:
- linux
- osx
dist: trusty
branches:
only:
- master
- develop
- /feature\/.*/
env:
matrix:
- BOGUS_JOB=true
matrix:
exclude:
- env: BOGUS_JOB=true
include:
- os: linux
compiler: g++
env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11
- os: linux
compiler: g++-4.4
env: TOOLSET=gcc COMPILER=g++-4.4 CXXSTD=98,0x
addons:
apt:
packages:
- g++-4.4
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-4.6
env: TOOLSET=gcc COMPILER=g++-4.6 CXXSTD=03,0x
addons:
apt:
packages:
- g++-4.6
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-4.7
env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=03,11
addons:
apt:
packages:
- g++-4.7
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-4.8
env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=03,11
addons:
apt:
packages:
- g++-4.8
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-4.9
env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=03,11
addons:
apt:
packages:
- g++-4.9
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-5
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- g++-5
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-6
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- g++-6
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-7
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-8
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=03,11,14
addons:
apt:
packages:
- g++-8
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-8
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=17,2a
addons:
apt:
packages:
- g++-8
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-9
env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=03,11,14
addons:
apt:
packages:
- g++-9
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-9
env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=17,2a
addons:
apt:
packages:
- g++-9
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-7
env: UBSAN=1 TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11
- os: linux
compiler: /usr/bin/clang++
env: TOOLSET=clang COMPILER=/usr/bin/clang++ CXXSTD=03,11
addons:
apt:
packages:
- clang-3.3
- os: linux
compiler: /usr/bin/clang++
env: TOOLSET=clang COMPILER=/usr/bin/clang++ CXXSTD=03,11
addons:
apt:
packages:
- clang-3.4
- os: linux
compiler: clang++-3.5
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.5
- libstdc++-4.9-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.5
- os: linux
compiler: clang++-3.6
env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.6
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.6
- os: linux
compiler: clang++-3.7
env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
- os: linux
compiler: clang++-3.8
env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.8
- libstdc++-4.9-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
- os: linux
compiler: clang++-3.9
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.9
- libstdc++-4.9-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.9
- os: linux
compiler: clang++-4.0
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-4.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- os: linux
compiler: clang++-5.0
env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-5.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-5.0
- os: linux
compiler: clang++-6.0
env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-6.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-6.0
- os: linux
compiler: clang++-7
env: TOOLSET=clang COMPILER=clang++-7 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7
- os: linux
compiler: clang++-8
env: TOOLSET=clang COMPILER=clang++-8 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-8
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-8
- os: linux
compiler: clang++-7
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-7 CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
- clang-7
- libstdc++-5-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7
- os: linux
compiler: clang++-libc++
env: TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z
addons:
apt:
packages:
- libc++-dev
- os: linux
compiler: clang++-libc++
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
- libc++-dev
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
- os: linux
compiler: g++
env: CMAKE_SUBDIR_TEST=1
script:
- cd libs/smart_ptr/test/cmake_subdir_test && mkdir __build__ && cd __build__
- cmake ..
- cmake --build .
- cmake --build . --target check
install:
- git clone -b $TRAVIS_BRANCH https://github.com/boostorg/boost.git boost
- cd boost
- BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
- cd ..
- git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root
- cd boost-root
- git submodule init libs/align
- git submodule init libs/assert
- git submodule init libs/atomic
- git submodule init libs/config
- git submodule init libs/container_hash
- git submodule init libs/core
- git submodule init libs/detail
- git submodule init libs/functional
- git submodule init libs/integer
- git submodule init libs/move
- git submodule init libs/predef
- git submodule init libs/preprocessor
- git submodule init libs/smart_ptr
- git submodule init libs/static_assert
- git submodule init libs/throw_exception
- git submodule init libs/type_traits
- git submodule init libs/detail
- git submodule init libs/integer
- git submodule init tools/build
- git submodule init tools/inspect
- git submodule update
- cd libs/smart_ptr
- git checkout -q $TRAVIS_COMMIT
- cd ../..
- git submodule init libs/headers
- git submodule init tools/boost_install
- git submodule update --jobs 3
- cp -r $TRAVIS_BUILD_DIR/* libs/smart_ptr
- ./bootstrap.sh
- ./b2 headers
script:
- TOOLSET=gcc,clang
- if [ $TRAVIS_OS_NAME == osx ]; then TOOLSET=clang; fi
- ./b2 libs/smart_ptr/test toolset=$TOOLSET
- |-
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
- ./b2 -j3 libs/smart_ptr/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
notifications:
email:
on_success: always

26
CMakeLists.txt Normal file
View File

@@ -0,0 +1,26 @@
# Copyright 2018 Mike Dev
# 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
# Partial (add_subdirectory only) and experimental CMake support
# Subject to change; please do not rely on the contents of this file yet
cmake_minimum_required(VERSION 3.5)
project(BoostSmartPtr LANGUAGES CXX)
add_library(boost_smart_ptr INTERFACE)
add_library(Boost::smart_ptr ALIAS boost_smart_ptr)
target_include_directories(boost_smart_ptr INTERFACE include)
target_link_libraries(boost_smart_ptr
INTERFACE
Boost::assert
Boost::config
Boost::core
Boost::move
Boost::predef
Boost::static_assert
Boost::throw_exception
Boost::type_traits
)

View File

@@ -2,5 +2,5 @@
Branch | Travis | Appveyor
---------|--------|---------
Develop | [![Build Status](https://travis-ci.org/boostorg/smart_ptr.svg?branch=develop)](https://travis-ci.org/boostorg/smart_ptr) | [![Build Status](https://ci.appveyor.com/api/projects/status/github/boostorg/smart_ptr?branch=develop&svg=true)](https://ci.appveyor.com/project/pdimov/smart_ptr)
Master | [![Build Status](https://travis-ci.org/boostorg/smart_ptr.svg?branch=master)](https://travis-ci.org/boostorg/smart_ptr) | [![Build Status](https://ci.appveyor.com/api/projects/status/github/boostorg/smart_ptr?branch=master&svg=true)](https://ci.appveyor.com/project/pdimov/smart_ptr)
Develop | [![Build Status](https://travis-ci.org/boostorg/smart_ptr.svg?branch=develop)](https://travis-ci.org/boostorg/smart_ptr) | [![Build Status](https://ci.appveyor.com/api/projects/status/github/boostorg/smart_ptr?branch=develop&svg=true)](https://ci.appveyor.com/project/pdimov/smart-ptr)
Master | [![Build Status](https://travis-ci.org/boostorg/smart_ptr.svg?branch=master)](https://travis-ci.org/boostorg/smart_ptr) | [![Build Status](https://ci.appveyor.com/api/projects/status/github/boostorg/smart_ptr?branch=master&svg=true)](https://ci.appveyor.com/project/pdimov/smart-ptr)

View File

@@ -1,4 +1,4 @@
# Copyright 2016 Peter Dimov
# Copyright 2016-2019 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
@@ -10,35 +10,75 @@ branches:
only:
- master
- develop
- /feature\/.*/
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-12.0,msvc-14.0
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
CXXSTD: 14,17
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: clang-win
CXXSTD: 14,17
ADDRMD: 64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2
CXXSTD: 14,17
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin64\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\mingw\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin;
TOOLSET: gcc
CXXSTD: 03,11,14,1z
install:
- git clone -b %APPVEYOR_REPO_BRANCH% https://github.com/boostorg/boost.git boost
- cd boost
- set BOOST_BRANCH=develop
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
- cd ..
- git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
- cd boost-root
- git submodule init libs/align
- git submodule init libs/assert
- git submodule init libs/atomic
- git submodule init libs/config
- git submodule init libs/container_hash
- git submodule init libs/core
- git submodule init libs/detail
- git submodule init libs/functional
- git submodule init libs/integer
- git submodule init libs/move
- git submodule init libs/predef
- git submodule init libs/preprocessor
- git submodule init libs/smart_ptr
- git submodule init libs/static_assert
- git submodule init libs/throw_exception
- git submodule init libs/type_traits
- git submodule init libs/detail
- git submodule init libs/integer
- git submodule init tools/build
- git submodule init tools/inspect
- git submodule update
- cd libs\smart_ptr
- git checkout -q %APPVEYOR_REPO_COMMIT%
- cd ..\..
- bootstrap
- b2 headers
- git submodule init libs/headers
- git submodule init tools/boost_install
- git submodule update --jobs 3
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\smart_ptr\
- cmd /c bootstrap
- b2 -d0 headers
build: off
test_script:
- b2 libs/smart_ptr/test toolset=msvc-9.0,msvc-10.0,msvc-11.0,msvc-12.0
- PATH=%ADDPATH%%PATH%
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
- b2 -j3 libs/smart_ptr/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release

View File

@@ -1,88 +0,0 @@
<!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 text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
width="277" align="middle" border="0">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>$Date$</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>

2
doc/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/html/
/pdf/

24
doc/Jamfile Normal file
View File

@@ -0,0 +1,24 @@
# Copyright 2017 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
import asciidoctor ;
html smart_ptr.html : smart_ptr.adoc ;
install html_ : smart_ptr.html : <location>html ;
pdf smart_ptr.pdf : smart_ptr.adoc ;
explicit smart_ptr.pdf ;
install pdf_ : smart_ptr.pdf : <location>pdf ;
explicit pdf_ ;
###############################################################################
alias boostdoc ;
explicit boostdoc ;
alias boostrelease : html_ ;
explicit boostrelease ;

View File

@@ -0,0 +1,6 @@
<style>
*:not(pre)>code { background: none; color: #600000; }
table tr.even, table tr.alt, table tr:nth-of-type(even) { background: none; }
</style>

82
doc/smart_ptr.adoc Normal file
View File

@@ -0,0 +1,82 @@
////
Copyright 2017 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
////
# Boost.SmartPtr: The Smart Pointer Library
Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes
:toc: left
:toclevels: 2
:idprefix:
:listing-caption: Code Example
:docinfo: private-footer
:leveloffset: +1
include::smart_ptr/introduction.adoc[]
include::smart_ptr/changelog.adoc[]
include::smart_ptr/scoped_ptr.adoc[]
include::smart_ptr/scoped_array.adoc[]
include::smart_ptr/shared_ptr.adoc[]
include::smart_ptr/weak_ptr.adoc[]
include::smart_ptr/make_shared.adoc[]
include::smart_ptr/enable_shared_from_this.adoc[]
include::smart_ptr/enable_shared_from.adoc[]
include::smart_ptr/make_unique.adoc[]
include::smart_ptr/allocate_unique.adoc[]
include::smart_ptr/intrusive_ptr.adoc[]
include::smart_ptr/intrusive_ref_counter.adoc[]
include::smart_ptr/local_shared_ptr.adoc[]
include::smart_ptr/make_local_shared.adoc[]
include::smart_ptr/pointer_cast.adoc[]
include::smart_ptr/pointer_to_other.adoc[]
include::smart_ptr/atomic_shared_ptr.adoc[]
// appendix
include::smart_ptr/techniques.adoc[]
// appendix
include::smart_ptr/history.adoc[]
// appendix, deprecated
include::smart_ptr/shared_array.adoc[]
:leveloffset: -1
[[copyright]]
[appendix]
## Copyright and License
This documentation is
* Copyright 1999 Greg Colvin
* Copyright 1999 Beman Dawes
* Copyright 2002 Darin Adler
* Copyright 2003-2017 Peter Dimov
* Copyright 2005, 2006 Ion Gaztañaga
* Copyright 2008 Frank Mori Hess
* Copyright 2012-2017 Glen Fernandes
* Copyright 2013 Andrey Semashev
and is distributed under the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0].

View File

@@ -0,0 +1,318 @@
////
Copyright 2019 Glen Joseph Fernandes (glenjofe@gmail.com)
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
////
[#allocate_unique]
# allocate_unique: Creating unique_ptr
:toc:
:toc-title:
:idprefix: allocate_unique_
## Description
The `allocate_unique` family of function templates provide convenient and safe
ways to obtain a `std::unique_ptr` that manages a new object created using an
allocator.
## Rationale
The {cpp}14 standard introduced `std::make_unique` which used operator `new` to
create new objects. However, there is no convenient facility in the standard
library to use an allocator for the creation of the objects managed by
`std::unique_ptr`. Users writing allocator aware code have often requested an
`allocate_unique` factory function. This function is to `std::unique_ptr` what
`std::allocate_shared` is to `std::shared_ptr`.
## Synopsis
`allocate_unique` is defined in `<boost/smart_ptr/allocate_unique.hpp>`.
[subs=+quotes]
```
namespace boost {
template<class T, class A>
class alloc_deleter;
template<class T, class A>
using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A>>;
`// T is not an array`
template<class T, class A, class... Args>
std::unique_ptr<T, alloc_deleter<T, A>>
allocate_unique(const A& a, Args&&... args);
`// T is not an array`
template<class T, class A>
std::unique_ptr<T, alloc_deleter<T, A>>
allocate_unique(const A& a, type_identity_t<T>&& v);
`// T is an array of unknown bounds`
template<class T, class A>
std::unique_ptr<T, alloc_deleter<T, A>>
allocate_unique(const A& a, std::size_t n);
`// T is an array of known bounds`
template<class T, class A>
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
allocate_unique(const A& a);
`// T is an array of unknown bounds`
template<class T, class A>
std::unique_ptr<T, alloc_deleter<T, A>>
allocate_unique(const A& a, std::size_t n, const remove_extent_t<T>& v);
`// T is an array of known bounds`
template<class T, class A>
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
allocate_unique(const A& a, const remove_extent_t<T>& v);
`// T is not an array`
template<class T, class A>
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
allocate_unique_noinit(const A& a);
`// T is an array of unknown bounds`
template<class T, class A>
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
allocate_unique_noinit(const A& a, std::size_t n);
`// T is an array of known bounds`
template<class T, class A>
std::unique_ptr<remove_extent_t<T>[], alloc_noinit_deleter<T, A>>
allocate_unique_noinit(const A& a);
}
```
## Common Requirements
The common requirements that apply to all `allocate_unique` and
`allocate_unique_noinit` overloads, unless specified otherwise, are described
below.
Requires:: `A` shall be an _allocator_. The copy constructor and destructor
of `A` shall not throw exceptions.
Effects:: Allocates memory for an object of type `T` or `n` objects of `U`
(if `T` is an array type of the form `U[]` and `n` is determined by
arguments, as specified by the concrete overload). The object is initialized
from arguments as specified by the concrete overload. Uses a rebound copy of
`a` (for an unspecified `value_type`) to allocate memory. If an exception is
thrown, the functions have no effect.
Returns:: A `std::unique_ptr` instance that stores and owns the address of the
newly constructed object.
Postconditions:: `r.get() != 0`, where `r` is the return value.
Throws:: An exception thrown from `A::allocate`, or from the initialization of
the object.
Remarks::
* When an object of an array type is specified to be initialized to a value of
the same type `v`, this shall be interpreted to mean that each array element
of the object is initialized to the corresponding element from `v`.
* When an object of an array type is specified to be value-initialized, this
shall be interpreted to mean that each array element of the object is
value-initialized.
* When a (sub)object of non-array type `U` is specified to be initialized to a
value `v`, or constructed from `args\...`, `allocate_unique` shall perform this
initialization via the expression
`std::allocator_traits<A2>::construct(a2, p, expr)` (where `_expr_` is `v` or
`std::forward<Args>(args)\...)` respectively), `p` points to storage suitable
to hold an object of type `U`, and `a2` of type `A2` is a potentially rebound
copy of `a`.
* When a (sub)object of non-array type `U` is specified to be
default-initialized, `allocate_unique_noinit` shall perform this initialization
via the expression `::new(p) U`, where `p` has type `void*` and points to
storage suitable to hold an object of type `U`.
* When a (sub)object of non-array type `U` is specified to be
value-initialized, `allocate_unique` shall perform this initialization via the
expression `std::allocator_traits<A2>::construct(a2, p)`, where `p` points to
storage suitable to hold an object of type `U` and `a2` of type `A2` is a
potentially rebound copy of `a`.
* Array elements are initialized in ascending order of their addresses.
* When the lifetime of the object managed by the return value ends, or when the
initialization of an array element throws an exception, the initialized
elements should be destroyed in the reverse order of their construction.
## Free Functions
```
template<class T, class A, class... Args>
std::unique_ptr<T, alloc_deleter<T, A>>
allocate_unique(const A& a, Args&&... args);
```
[none]
* {blank}
+
Constraints:: `T` is not an array.
Returns:: A `std::unique_ptr` to an object of type `T`, constructed from
`args\...`.
Examples::
* `auto p = allocate_unique<int>(a);`
* `auto p = allocate_unique<std::vector<int>>(a, 16, 1);`
```
template<class T, class A>
std::unique_ptr<T, alloc_deleter<T, A>>
allocate_unique(const A& a, type_identity_t<T>&& v);
```
[none]
* {blank}
+
Constraints:: `T` is not an array.
Returns:: A `std::unique_ptr` to an object of type `T`, constructed from `v`.
Example:: `auto p = allocate_unique<std::vector<int>>(a, {1, 2});`
```
template<class T, class A>
std::unique_ptr<T, alloc_deleter<T, A>>
allocate_unique(const A& a, std::size_t n);
```
[none]
* {blank}
+
Constraints:: `T` is an array of unknown bounds.
Returns:: A `std::unique_ptr` to a sequence of `n` value-initialized objects of
type `remove_extent_t<T>`.
Examples::
* `auto p = allocate_unique<double[]>(a, 1024);`
* `auto p = allocate_unique<double[][2][2]>(a, 6);`
```
template<class T, class A>
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
allocate_unique(const A& a);
```
[none]
* {blank}
+
Constraints:: `T` is an array of known bounds.
Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` value-initialized
objects of type `remove_extent_t<T>`.
Examples::
* `auto p = allocate_unique<double[1024]>(a);`
* `auto p = allocate_unique<double[6][2][2]>(a);`
```
template<class T, class A>
std::unique_ptr<T, alloc_deleter<T, A>>
allocate_unique(const A& a, std::size_t n, const remove_extent_t<T>& v);
```
[none]
* {blank}
+
Constraints:: `T` is an array of unknown bounds.
Returns:: A `std::unique_ptr` to a sequence of `n` objects of type
`remove_extent_t<T>`, each initialized to `v`.
Examples::
* `auto p = allocate_unique<double[]>(a, 1024, 1.0);`
* `auto p = allocate_unique<double[][2]>(a, 6, {1.0, 0.0});`
* `auto p = allocate_unique<std::vector<int>[]>(a, 4, {1, 2});`
```
template<class T, class A>
std::unique_ptr<remove_extent_t<T>[], alloc_deleter<T, A>>
allocate_unique(const A& a, const remove_extent_t<T>& v);
```
[none]
* {blank}
+
Constraints:: `T` is an array of known bounds.
Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>` objects of type
`remove_extent_t<T>`, each initialized to `v`.
Examples::
* `auto p = allocate_unique<double[1024]>(a, 1.0);`
* `auto p = allocate_unique<double[6][2]>(a, {1.0, 0.0});`
* `auto p = allocate_unique<std::vector<int>[4]>(a, {1, 2});`
```
template<class T, class A>
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
allocate_unique_noinit(const A& a);
```
[none]
* {blank}
+
Constraints:: `T` is not an array.
Returns:: A `std::unique_ptr` to a default-initialized object of type `T`.
Example:: `auto p = allocate_unique_noinit<double>(a);`
```
template<class T, class A>
std::unique_ptr<T, alloc_noinit_deleter<T, A>>
allocate_unique_noinit(const A& a, std::size_t n);
```
[none]
* {blank}
+
Constraints:: `T` is an array of unknown bounds.
Returns:: A `std::unique_ptr` to a sequence of `n` default-initialized objects
of type `remove_extent_t<T>`.
Example:: `auto p = allocate_unique_noinit<double[]>(a, 1024);`
```
template<class T, class A>
std::unique_ptr<remove_extent_t<T>, alloc_noinit_deleter<T, A>>
allocate_unique_noinit(const A& a);
```
[none]
* {blank}
+
Constraints:: `T` is an array of known bounds.
Returns:: A `std::unique_ptr` to a sequence of `extent_v<T>`
default-initialized objects of type `remove_extent_t<T>`.
Example:: `auto p = allocate_unique_noinit<double[1024]>(a);`
## Deleter
Class template `alloc_deleter` is the deleter used by the `allocate_unique`
functions.
### Synopsis
[subs=+quotes]
```
template<class T, class A>
class alloc_deleter {
public:
using pointer = `unspecified`;
explicit alloc_deleter(const A& a) noexcept;
void operator()(pointer p);
};
```
### Members
[subs=+quotes]
```
using pointer = `unspecified`;
```
[none]
* {blank}
+
A type that satisfies _NullablePointer_.
```
explicit alloc_deleter(const A& a) noexcept;
```
[none]
* {blank}
+
Effects:: Initializes the stored allocator from `a`.
```
void operator()(pointer p);
```
[none]
* {blank}
+
Effects:: Destroys the objects and deallocates the storage referenced by `p`,
using the stored allocator.

View File

@@ -0,0 +1,170 @@
////
Copyright 2017 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
////
[#atomic_shared_ptr]
# atomic_shared_ptr
:toc:
:toc-title:
:idprefix: atomic_shared_ptr_
## Description
The class template `atomic_shared_ptr<T>` implements the interface of `std::atomic`
for a contained value of type `shared_ptr<T>`. Concurrent access to `atomic_shared_ptr`
is not a data race.
## Synopsis
`atomic_shared_ptr` is defined in `<boost/smart_ptr/atomic_shared_ptr.hpp>`.
```
namespace boost {
template<class T> class atomic_shared_ptr {
private:
shared_ptr<T> p_; // exposition only
atomic_shared_ptr(const atomic_shared_ptr&) = delete;
atomic_shared_ptr& operator=(const atomic_shared_ptr&) = delete;
public:
constexpr atomic_shared_ptr() noexcept;
atomic_shared_ptr( shared_ptr<T> p ) noexcept;
atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept;
bool is_lock_free() const noexcept;
shared_ptr<T> load( int = 0 ) const noexcept;
operator shared_ptr<T>() const noexcept;
void store( shared_ptr<T> r, int = 0 ) noexcept;
shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept;
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
};
}
```
## Members
```
constexpr atomic_shared_ptr() noexcept;
```
[none]
* {blank}
+
Effects:: Default-initializes `p_`.
```
atomic_shared_ptr( shared_ptr<T> p ) noexcept;
```
[none]
* {blank}
+
Effects:: Initializes `p_` to `p`.
```
atomic_shared_ptr& operator=( shared_ptr<T> r ) noexcept;
```
[none]
* {blank}
+
Effects:: `p_.swap(r)`.
Returns:: `*this`.
```
bool is_lock_free() const noexcept;
```
[none]
* {blank}
+
Returns:: `false`.
NOTE: This implementation is not lock-free.
```
shared_ptr<T> load( int = 0 ) const noexcept;
```
```
operator shared_ptr<T>() const noexcept;
```
[none]
* {blank}
+
Returns:: `p_`.
NOTE: The `int` argument is intended to be of type `memory_order`, but is ignored.
This implementation is lock-based and therefore always sequentially consistent.
```
void store( shared_ptr<T> r, int = 0 ) noexcept;
```
[none]
* {blank}
+
Effects:: `p_.swap(r)`.
```
shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) noexcept;
```
[none]
* {blank}
+
Effects:: `p_.swap(r)`.
Returns:: The old value of `p_`.
```
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
```
```
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
```
```
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) noexcept;
```
```
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) noexcept;
```
[none]
* {blank}
+
Effects:: If `p_` is equivalent to `v`, assigns `w` to `p_`, otherwise assigns `p_` to `v`.
Returns:: `true` if `p_` was equivalent to `v`, `false` otherwise.
Remarks:: Two `shared_ptr` instances are equivalent if they store the same pointer value and _share ownership_.
```
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
```
```
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
```
```
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) noexcept;
```
```
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) noexcept;
```
[none]
* {blank}
+
Effects:: If `p_` is equivalent to `v`, assigns `std::move(w)` to `p_`, otherwise assigns `p_` to `v`.
Returns:: `true` if `p_` was equivalent to `v`, `false` otherwise.
Remarks:: The old value of `w` is not preserved in either case.

View File

@@ -0,0 +1,29 @@
////
Copyright 2019 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
////
[#changelog]
# Revision History
:toc:
:toc-title:
:idprefix: changelog_
## Changes in 1.72.0
* Added `allocate_unique`
## Changes in 1.71.0
* Added aliasing constructors to `weak_ptr`
* Added `weak_ptr<T>::empty()`
* Added `enable_shared_from`, `shared_from`, and `weak_from`
## Changes in 1.65.0
* Added `atomic_shared_ptr`
* Added `local_shared_ptr`, `make_local_shared`

View File

@@ -0,0 +1,89 @@
////
Copyright 2002, 2003, 2015, 2017, 2019 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
////
[#enable_shared_from]
# enable_shared_from
:toc:
:toc-title:
:idprefix: enable_shared_from_
## Description
`enable_shared_from` is used as a base class that allows a `shared_ptr` or a
`weak_ptr` to be obtained given a raw pointer to the object, by using the
functions `shared_from` and `weak_from`.
`enable_shared_from` differs from `enable_shared_from_this<T>` by the fact
that it's not a template, and is its recommended replacement for new code.
## Example
```
#include <boost/smart_ptr/enable_shared_from.hpp>
#include <boost/shared_ptr.hpp>
#include <cassert>
class Y: public boost::enable_shared_from
{
public:
boost::shared_ptr<Y> f()
{
return boost::shared_from( this );
}
};
int main()
{
boost::shared_ptr<Y> p(new Y);
boost::shared_ptr<Y> q = p->f();
assert(p == q);
assert(!(p < q || q < p)); // p and q must share ownership
}
```
## Synopsis
`enable_shared_from` is defined in `<boost/smart_ptr/enable_shared_from.hpp>`.
```
namespace boost {
class enable_shared_from: public enable_shared_from_this<enable_shared_from>
{
};
template<class T> shared_ptr<T> shared_from( T * p );
template<class T> weak_ptr<T> weak_from( T * p ) noexcept;
}
```
## Functions
```
template<class T> shared_ptr<T> shared_from( T * p );
```
[none]
* {blank}
+
Returns:: `shared_ptr<T>( p\->enable_shared_from::shared_from_this(), p )`.
NOTE: Throws `bad_weak_ptr` when `p` is not owned by a `shared_ptr`.
```
template<class T> weak_ptr<T> weak_from( T * p ) noexcept;
```
[none]
* {blank}
+
Returns:: `weak_ptr<T>( p\->enable_shared_from::weak_from_this(), p )`.
NOTE: Unlike `shared_from(this)`, `weak_from(this)` is valid in a destructor
and returns a `weak_ptr` that is `expired()` but still shares ownership
with other `weak_ptr` instances (if any) that refer to the object.

View File

@@ -0,0 +1,148 @@
////
Copyright 2002, 2003, 2015, 2017 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
////
[#enable_shared_from_this]
# enable_shared_from_this
:toc:
:toc-title:
:idprefix: enable_shared_from_this_
## Description
The class template `enable_shared_from_this` is used as a base class that allows
a `shared_ptr` or a `weak_ptr` to the current object to be obtained from within a
member function.
`enable_shared_from_this<T>` defines two member functions called `shared_from_this`
that return a `shared_ptr<T>` and `shared_ptr<T const>`, depending on constness, to
`this`. It also defines two member functions called `weak_from_this` that return a
corresponding `weak_ptr`.
## Example
```
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <cassert>
class Y: public boost::enable_shared_from_this<Y>
{
public:
boost::shared_ptr<Y> f()
{
return shared_from_this();
}
};
int main()
{
boost::shared_ptr<Y> p(new Y);
boost::shared_ptr<Y> q = p->f();
assert(p == q);
assert(!(p < q || q < p)); // p and q must share ownership
}
```
## Synopsis
`enable_shared_from_this` is defined in `<boost/smart_ptr/enable_shared_from_this.hpp>`.
```
namespace boost {
template<class T> class enable_shared_from_this {
private:
// exposition only
weak_ptr<T> weak_this_;
protected:
enable_shared_from_this() = default;
~enable_shared_from_this() = default;
enable_shared_from_this(const enable_shared_from_this&) noexcept;
enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept;
public:
shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;
weak_ptr<T> weak_from_this() noexcept;
weak_ptr<T const> weak_from_this() const noexcept;
}
}
```
## Members
```
enable_shared_from_this(enable_shared_from_this const &) noexcept;
```
[none]
* {blank}
+
Effects:: Default-constructs `weak_this_`.
NOTE: `weak_this_` is _not_ copied from the argument.
```
enable_shared_from_this& operator=(enable_shared_from_this const &) noexcept;
```
[none]
* {blank}
+
Returns:: `*this`.
NOTE: `weak_this_` is unchanged.
```
template<class T> shared_ptr<T> shared_from_this();
```
```
template<class T> shared_ptr<T const> shared_from_this() const;
```
[none]
* {blank}
+
Returns:: `shared_ptr<T>(weak_this_)`.
NOTE: These members throw `bad_weak_ptr` when `*this` is not owned by a `shared_ptr`.
[NOTE]
====
`weak_this_` is initialized by `shared_ptr` to a copy of itself when it's constructed by a pointer to `*this`.
For example, in the following code:
```
class Y: public boost::enable_shared_from_this<Y> {};
int main()
{
boost::shared_ptr<Y> p(new Y);
}
```
the construction of `p` will automatically initialize `p\->weak_this_` to `p`.
====
```
template<class T> weak_ptr<T> weak_from_this() noexcept;
```
```
template<class T> weak_ptr<T const> weak_from_this() const noexcept;
```
[none]
* {blank}
+
Returns:: `weak_this_`.
NOTE: Unlike `shared_from_this()`, `weak_from_this()` is valid in a destructor
and returns a `weak_ptr` that is `expired()` but still shares ownership
with other `weak_ptr` instances (if any) that refer to the object.

117
doc/smart_ptr/history.adoc Normal file
View File

@@ -0,0 +1,117 @@
////
Copyright 1999 Greg Colvin and Beman Dawes
Copyright 2002 Darin Adler
Copyright 2017 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
////
[[history]]
[appendix]
# History and Acknowledgments
:idprefix: history_
## Summer 1994
Greg Colvin http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1994/N0555.pdf[proposed]
to the {cpp} Standards Committee classes named `auto_ptr` and `counted_ptr` which were very
similar to what we now call `scoped_ptr` and `shared_ptr`. In one of the very few cases
where the Library Working Group's recommendations were not followed by the full committee,
`counted_ptr` was rejected and surprising transfer-of-ownership semantics were added to `auto_ptr`.
## October 1998
Beman Dawes proposed reviving the original semantics under the names `safe_ptr` and `counted_ptr`,
meeting of Per Andersson, Matt Austern, Greg Colvin, Sean Corfield, Pete Becker, Nico Josuttis,
Dietmar Kü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 `std::auto_ptr`
interface, and various function signatures and semantics were finalized.
Over the next three months, several implementations were considered for `shared_ptr`, and discussed
on the http://www.boost.org/[boost.org] 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:
* Direct detached: the `shared_ptr` contains a pointer to the object, and a pointer to the count.
* Indirect detached: the `shared_ptr` contains a pointer to a helper object, which in turn contains a pointer to the object and the count.
* Embedded attached: the count is a member of the object pointed to.
* Placement attached: the count is attached via operator new manipulations.
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ühl
suggested an elegant partial template specialization technique to allow users to choose which implementation
they preferred, and that was also experimented with.
But Greg Colvin and Jerry Schwarz argued that "parameterization will discourage users", and in the end we choose
to supply only the direct implementation.
## May 1999
In April and May, 1999, Valentin Bonnard and David Abrahams made a number of suggestions resulting in numerous improvements.
## September 1999
Luis Coelho provided `shared_ptr::swap` and `shared_array::swap`.
## November 1999
Darin Adler provided `operator ==`, `operator !=`, and `std::swap` and `std::less` specializations for shared types.
## 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.
## January 2002
Peter Dimov reworked all four classes, adding features, fixing bugs, splitting them into four separate headers, and adding
`weak_ptr`.
## March 2003
Peter Dimov, Beman Dawes and Greg Colvin http://open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html[proposed] `shared_ptr`
and `weak_ptr` for inclusion in the Standard Library via the first Library Technical Report (known as TR1). The proposal was
accepted and eventually went on to become a part of the {cpp} standard in its 2011 iteration.
## July 2007
Peter Dimov and Beman Dawes http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm[proposed] a number of enhancements
to `shared_ptr` as it was entering the working paper that eventually became the {cpp}11 standard.
## November 2012
Glen Fernandes provided implementations of `make_shared` and `allocate_shared` for arrays. They achieve a single allocation
for an array that can be initialized with constructor arguments or initializer lists as well as overloads for default initialization
and no value initialization.
Peter Dimov aided this development by extending `shared_ptr` to support arrays via the syntax `shared_ptr<T[]>` and `shared_ptr<T[N]>`.
## April 2013
Peter Dimov http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3640.html[proposed] the extension of `shared_ptr` to support
arrays for inclusion into the standard, and it was accepted.
## February 2014
Glen Fernandes updated `make_shared` and `allocate_shared` to conform to the specification in {cpp} standard paper
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3870.html[N3870], and implemented `make_unique` for arrays and objects.
Peter Dimov and Glen Fernandes updated the scalar and array implementations, respectively, to resolve {cpp} standard library defect 2070.
## February 2017
Glen Fernandes rewrote `allocate_shared` and `make_shared` for arrays for a more optimal and more maintainable implementation.
## June 2017
Peter Dimov and Glen Fernandes rewrote the documentation in Asciidoc format.
Peter Dimov added `atomic_shared_ptr` and `local_shared_ptr`.
## August 2019
Glen Fernandes implemented `allocate_unique` for scalars and arrays.

View File

@@ -0,0 +1,52 @@
////
Copyright 1999 Greg Colvin and Beman Dawes
Copyright 2002 Darin Adler
Copyright 2017 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
////
[#introduction]
# Introduction
:toc:
:toc-title:
:idprefix: intro_
Smart pointers are objects which store pointers to dynamically allocated (heap) objects.
They behave much like built-in {cpp} 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.
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. As such, 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.
This library provides six smart pointer class templates:
* `<<scoped_ptr,scoped_ptr>>`, used to contain ownership of a dynamically allocated object to the current scope;
* `<<scoped_array,scoped_array>>`, which provides scoped ownership for a dynamically allocated array;
* `<<shared_ptr,shared_ptr>>`, a versatile tool for managing shared ownership of an object or array;
* `<<weak_ptr,weak_ptr>>`, a non-owning observer to a shared_ptr-managed object that can be promoted temporarily to shared_ptr;
* `<<intrusive_ptr,intrusive_ptr>>`, a pointer to objects with an embedded reference count;
* `<<local_shared_ptr,local_shared_ptr>>`, providing shared ownership within a single thread.
`shared_ptr` and `weak_ptr` are part of the {cpp} standard since its 2011 iteration.
In addition, the library contains the following supporting utility functions and classes:
* `<<make_shared,make_shared>>`, a factory function for creating objects that returns a `shared_ptr`;
* `<<make_unique,make_unique>>`, a factory function returning `std::unique_ptr`;
* `<<allocate_unique,allocate_unique>>`, a factory function for creating objects using an allocator that returns a `std::unique_ptr`;
* `<<enable_shared_from_this,enable_shared_from_this>>`, a helper base class that enables the acquisition of a `shared_ptr` pointing to `this`;
* `<<pointer_to_other,pointer_to_other>>`, a helper trait for converting one smart pointer type to another;
* `<<pointer_cast,static_pointer_cast>>` and companions, generic smart pointer casts;
* `<<intrusive_ref_counter,intrusive_ref_counter>>`, a helper base class containing a reference count.
* `<<atomic_shared_ptr,atomic_shared_ptr>>`, a helper class implementing the interface of `std::atomic` for a value of type `shared_ptr`.
As a general rule, the destructor or `operator delete` for an object managed by pointers in the library
are not allowed to throw exceptions.

View File

@@ -0,0 +1,478 @@
////
Copyright 2003-2005, 2013, 2017 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
////
[#intrusive_ptr]
# intrusive_ptr: Managing Objects with Embedded Counts
:toc:
:toc-title:
:idprefix: intrusive_ptr_
## Description
The `intrusive_ptr` class template stores a pointer to an object with an embedded reference count.
Every new `intrusive_ptr` instance increments the reference count by using an unqualified call to the
function `intrusive_ptr_add_ref`, passing it the pointer as an argument. Similarly, when an `intrusive_ptr`
is destroyed, it calls `intrusive_ptr_release`; 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, `intrusive_ptr_add_ref` and `intrusive_ptr_release` should
be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace
`boost`. The library provides a helper base class template `<<intrusive_ref_counter,intrusive_ref_counter>>` which
may help adding support for `intrusive_ptr` to user types.
The class template is parameterized on `T`, the type of the object pointed to. `intrusive_ptr<T>` can be implicitly
converted to `intrusive_ptr<U>` whenever `T*` can be implicitly converted to `U*`.
The main reasons to use `intrusive_ptr` are:
* Some existing frameworks or OSes provide objects with embedded reference counts;
* The memory footprint of `intrusive_ptr` is the same as the corresponding raw pointer;
* `intrusive_ptr<T>` can be constructed from an arbitrary raw pointer of type `T*`.
As a general rule, if it isn't obvious whether `intrusive_ptr` better fits your needs than `shared_ptr`, try a `shared_ptr`-based design first.
## Synopsis
`intrusive_ptr` is defined in `<boost/smart_ptr/intrusive_ptr.hpp>`.
```
namespace boost {
template<class T> class intrusive_ptr {
public:
typedef T element_type;
intrusive_ptr() noexcept;
intrusive_ptr(T * p, bool add_ref = true);
intrusive_ptr(intrusive_ptr const & r);
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
intrusive_ptr(intrusive_ptr && r);
template<class Y> intrusive_ptr(intrusive_ptr<Y> && r);
~intrusive_ptr();
intrusive_ptr & operator=(intrusive_ptr const & r);
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
intrusive_ptr & operator=(T * r);
intrusive_ptr & operator=(intrusive_ptr && r);
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r);
void reset();
void reset(T * r);
void reset(T * r, bool add_ref);
T & operator*() const noexcept;
T * operator->() const noexcept;
T * get() const noexcept;
T * detach() noexcept;
explicit operator bool () const noexcept;
void swap(intrusive_ptr & b) noexcept;
};
template<class T, class U>
bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;
template<class T, class U>
bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;
template<class T, class U>
bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
template<class T>
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept;
template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;
template<class T, class U>
intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;
template<class T, class U>
intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;
template<class T, class U>
intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;
template<class E, class T, class Y>
std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
intrusive_ptr<Y> const & p);
}
```
## Members
### element_type
```
typedef T element_type;
```
Provides the type of the template parameter T.
### constructors
```
intrusive_ptr() noexcept;
```
[none]
* {blank}
+
Postconditions:: `get() == 0`.
```
intrusive_ptr(T * p, bool add_ref = true);
```
[none]
* {blank}
+
Effects:: `if(p != 0 && add_ref) intrusive_ptr_add_ref(p);`.
Postconditions:: `get() == p`.
```
intrusive_ptr(intrusive_ptr const & r);
```
```
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
```
[none]
* {blank}
+
Effects:: `T * p = r.get(); if(p != 0) intrusive_ptr_add_ref(p);`.
Postconditions:: `get() == r.get()`.
```
intrusive_ptr(intrusive_ptr && r);
```
```
template<class Y> intrusive_ptr(intrusive_ptr<Y> && r);
```
[none]
* {blank}
+
Postconditions:: `get()` equals the old value of `r.get()`. `r.get() == 0`.
### destructor
```
~intrusive_ptr();
```
[none]
* {blank}
+
Effects:: `if(get() != 0) intrusive_ptr_release(get());`.
### assignment
```
intrusive_ptr & operator=(intrusive_ptr const & r);
```
```
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
```
```
intrusive_ptr & operator=(T * r);
```
[none]
* {blank}
+
Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`.
Returns:: `*this`.
```
intrusive_ptr & operator=(intrusive_ptr && r);
```
```
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r);
```
[none]
* {blank}
+
Effects:: Equivalent to `intrusive_ptr(std::move(r)).swap(*this)`.
Returns:: `*this`.
### reset
```
void reset();
```
[none]
* {blank}
+
Effects:: Equivalent to `intrusive_ptr().swap(*this)`.
```
void reset(T * r);
```
[none]
* {blank}
+
Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`.
```
void reset(T * r, bool add_ref);
```
[none]
* {blank}
+
Effects:: Equivalent to `intrusive_ptr(r, add_ref).swap(*this)`.
### indirection
```
T & operator*() const noexcept;
```
[none]
* {blank}
+
Requirements:: `get() != 0`.
Returns:: `*get()`.
```
T * operator->() const noexcept;
```
[none]
* {blank}
+
Requirements:: `get() != 0`.
Returns:: `get()`.
### get
```
T * get() const noexcept;
```
[none]
* {blank}
+
Returns:: the stored pointer.
### detach
```
T * detach() noexcept;
```
[none]
* {blank}
+
Returns:: the stored pointer.
Postconditions:: `get() == 0`.
NOTE: The returned pointer has an elevated reference count. This allows conversion of an `intrusive_ptr`
back to a raw pointer, without the performance overhead of acquiring and dropping an extra reference.
It can be viewed as the complement of the non-reference-incrementing constructor.
CAUTION: Using `detach` escapes the safety of automatic reference counting provided by `intrusive_ptr`.
It should by used only where strictly necessary (such as when interfacing to an existing API), and when
the implications are thoroughly understood.
### conversions
```
explicit operator bool () const noexcept;
```
[none]
* {blank}
+
Returns:: `get() != 0`.
NOTE: This conversion operator allows `intrusive_ptr` objects to be used in boolean contexts,
like `if (p && p\->valid()) {}`.
NOTE: On C++03 compilers, the return value is of an unspecified type.
### swap
```
void swap(intrusive_ptr & b) noexcept;
```
[none]
* {blank}
+
Effects:: Exchanges the contents of the two smart pointers.
## Free Functions
### comparison
```
template<class T, class U>
bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: `a.get() == b.get()`.
```
template<class T, class U>
bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: `a.get() != b.get()`.
```
template<class T, class U>
bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;
```
[none]
* {blank}
+
Returns:: `a.get() == b`.
```
template<class T, class U>
bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;
```
[none]
* {blank}
+
Returns:: `a.get() != b`.
```
template<class T, class U>
bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: `a == b.get()`.
```
template<class T, class U>
bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: `a != b.get()`.
```
template<class T>
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: `std::less<T *>()(a.get(), b.get())`.
NOTE: Allows `intrusive_ptr` objects to be used as keys in associative containers.
### swap
```
template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `a.swap(b)`.
### get_pointer
```
template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;
```
[none]
* {blank}
+
Returns:: `p.get()`.
NOTE: Provided as an aid to generic programming. Used by `mem_fn`.
### static_pointer_cast
```
template<class T, class U>
intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;
```
[none]
* {blank}
+
Returns:: `intrusive_ptr<T>(static_cast<T*>(r.get()))`.
### const_pointer_cast
```
template<class T, class U>
intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;
```
[none]
* {blank}
+
Returns:: `intrusive_ptr<T>(const_cast<T*>(r.get()))`.
### dynamic_pointer_cast
```
template<class T, class U>
intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;
```
[none]
* {blank}
+
Returns:: `intrusive_ptr<T>(dynamic_cast<T*>(r.get()))`.
### operator<<
```
template<class E, class T, class Y>
std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,
intrusive_ptr<Y> const & p);
```
[none]
* {blank}
+
Effects:: `os << p.get();`.
Returns:: `os`.

View File

@@ -0,0 +1,153 @@
////
Copyright 2017 Peter Dimov
Copyright 2013 Andrey Semashev
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
////
[#intrusive_ref_counter]
# intrusive_ref_counter
:toc:
:toc-title:
:idprefix: intrusive_ref_counter_
## Description
The `intrusive_ref_counter` class template implements a reference counter for
a derived user's class that is intended to be used with `intrusive_ptr`. The
base class has associated `intrusive_ptr_add_ref` and `intrusive_ptr_release`
functions which modify the reference counter as needed and destroy the user's
object when the counter drops to zero.
The class template is parameterized on `Derived` and `CounterPolicy`
parameters. The first parameter is the user's class that derives from
`intrusive_ref_counter`. This type is needed in order to destroy the object
correctly when there are no references to it left.
The second parameter is a policy that defines the nature of the reference
counter. The library provides two such policies: `thread_unsafe_counter` and
`thread_safe_counter`. The former instructs the `intrusive_ref_counter` base
class to use a counter only suitable for a single-threaded use. Pointers to a
single object that uses this kind of reference counter must not be used in
different threads. The latter policy makes the reference counter thread-safe,
unless the target platform doesn't support threading. Since in modern systems
support for threading is common, the default counter policy is
`thread_safe_counter`.
## Synopsis
`intrusive_ref_counter` is defined in
`<boost/smart_ptr/intrusive_ref_counter.hpp>`.
```
namespace boost {
struct thread_unsafe_counter;
struct thread_safe_counter;
template<class Derived, class CounterPolicy = thread_safe_counter>
class intrusive_ref_counter {
public:
intrusive_ref_counter() noexcept;
intrusive_ref_counter(const intrusive_ref_counter& v) noexcept;
intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
unsigned int use_count() const noexcept;
protected:
~intrusive_ref_counter() = default;
};
template<class Derived, class CounterPolicy>
void intrusive_ptr_add_ref(
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
template<class Derived, class CounterPolicy>
void intrusive_ptr_release(
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
}
```
## Members
### Constructors
```
intrusive_ref_counter() noexcept;
```
```
intrusive_ref_counter(const intrusive_ref_counter&) noexcept;
```
[none]
* {blank}
+
Postconditions:: `use_count() == 0`.
NOTE: The pointer to the constructed object is expected to be passed to
`intrusive_ptr` constructor, assignment operator or `reset` method, which
would increment the reference counter.
### Destructor
```
~intrusive_ref_counter();
```
[none]
* {blank}
+
Effects:: Destroys the counter object.
NOTE: The destructor is protected so that the object can only be destroyed
through the `Derived` class.
### Assignment
```
intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
```
[none]
* {blank}
+
Effects:: Does nothing, reference counter is not modified.
### use_count
```
unsigned int use_count() const noexcept;
```
[none]
* {blank}
+
Returns:: The current value of the reference counter.
NOTE: The returned value may not be actual in multi-threaded applications.
## Free Functions
### intrusive_ptr_add_ref
```
template<class Derived, class CounterPolicy>
void intrusive_ptr_add_ref(
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
```
[none]
* {blank}
+
Effects:: Increments the reference counter.
### intrusive_ptr_release
```
template<class Derived, class CounterPolicy>
void intrusive_ptr_release(
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
```
[none]
* {blank}
+
Effects:: Decrements the reference counter. If the reference counter reaches
0, calls `delete static_cast<const Derived*>(p)`.

View File

@@ -0,0 +1,718 @@
////
Copyright 2017 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
////
[#local_shared_ptr]
# local_shared_ptr: Shared Ownership within a Single Thread
:toc:
:toc-title:
:idprefix: local_shared_ptr_
## Description
`local_shared_ptr` is nearly identical to `shared_ptr`, with the only difference of note being that its reference count is
updated with non-atomic operations. As such, a `local_shared_ptr` and all its copies must reside in (be local to) a single
thread (hence the name.)
`local_shared_ptr` can be converted to `shared_ptr` and vice versa. Creating a `local_shared_ptr` from a `shared_ptr` creates
a new local reference count; this means that two `local_shared_ptr` instances, both created from the same `shared_ptr`, refer
to the same object but don't share the same count, and as such, can safely be used by two different threads.
.Two local_shared_ptr instances created from a shared_ptr
```
shared_ptr<X> p1( new X );
local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
local_shared_ptr<X> p3( p1 ); // p3.local_use_count() also 1
```
Creating the second `local_shared_ptr` from the first one, however, does lead to the two sharing the same count:
.A local_shared_ptr created from another local_shared_ptr
```
shared_ptr<X> p1( new X );
local_shared_ptr<X> p2( p1 ); // p2.local_use_count() == 1
local_shared_ptr<X> p3( p2 ); // p3.local_use_count() == 2
```
Two `shared_ptr` instances created from the same `local_shared_ptr` do share ownership:
.Two shared_ptr instances created from a local_shared_ptr
```
local_shared_ptr<X> p1( new X );
shared_ptr<X> p2( p1 ); // p2.use_count() == 2
shared_ptr<X> p3( p1 ); // p3.use_count() == 3
```
Here `p2.use_count()` is 2, because `p1` holds a reference, too.
One can think of `local_shared_ptr<T>` as `shared_ptr<shared_ptr<T>>`, with the outer `shared_ptr` using non-atomic operations for
its count. Converting from `local_shared_ptr` to `shared_ptr` gives you a copy of the inner `shared_ptr`; converting from `shared_ptr`
wraps it into an outer `shared_ptr` with a non-atomic use count (conceptually speaking) and returns the result.
## Synopsis
`local_shared_ptr` is defined in `<boost/smart_ptr/local_shared_ptr.hpp>`.
```
namespace boost {
template<class T> class local_shared_ptr {
public:
typedef /*see below*/ element_type;
// constructors
constexpr local_shared_ptr() noexcept;
constexpr local_shared_ptr(std::nullptr_t) noexcept;
template<class Y> explicit local_shared_ptr(Y * p);
template<class Y, class D> local_shared_ptr(Y * p, D d);
template<class D> local_shared_ptr(std::nullptr_t p, D d);
template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);
template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);
local_shared_ptr(local_shared_ptr const & r) noexcept;
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;
local_shared_ptr(local_shared_ptr && r) noexcept;
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;
template<class Y> local_shared_ptr( shared_ptr<Y> const & r );
template<class Y> local_shared_ptr( shared_ptr<Y> && r );
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;
template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);
// destructor
~local_shared_ptr() noexcept;
// assignment
local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;
local_shared_ptr & operator=(local_shared_ptr const && r) noexcept;
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const && r) noexcept;
template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);
local_shared_ptr & operator=(std::nullptr_t) noexcept;
// reset
void reset() noexcept;
template<class Y> void reset(Y * p);
template<class Y, class D> void reset(Y * p, D d);
template<class Y, class D, class A> void reset(Y * p, D d, A a);
template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept;
template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;
// accessors
T & operator*() const noexcept; // only valid when T is not an array type
T * operator->() const noexcept; // only valid when T is not an array type
// only valid when T is an array type
element_type & operator[](std::ptrdiff_t i) const noexcept;
element_type * get() const noexcept;
long local_use_count() const noexcept;
// conversions
explicit operator bool() const noexcept;
template<class Y> operator shared_ptr<Y>() const noexcept;
template<class Y> operator weak_ptr<Y>() const noexcept;
// swap
void swap(local_shared_ptr & b) noexcept;
// owner_before
template<class Y> bool owner_before(local_shared_ptr<Y> const & rhs) const noexcept;
};
// comparisons
template<class T, class U>
bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
template<class T, class U>
bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
template<class T, class U>
bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
// swap
template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;
// get_pointer
template<class T>
typename local_shared_ptr<T>::element_type *
get_pointer(local_shared_ptr<T> const & p) noexcept;
// casts
template<class T, class U>
local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;
template<class T, class U>
local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;
template<class T, class U>
local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;
template<class T, class U>
local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;
// stream I/O
template<class E, class T, class Y>
std::basic_ostream<E, T> &
operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);
// get_deleter
template<class D, class T> D * get_deleter(local_shared_ptr<T> const & p) noexcept;
}
```
## Members
### element_type
```
typedef ... element_type;
```
`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`.
### default constructor
```
constexpr local_shared_ptr() noexcept;
```
```
constexpr local_shared_ptr(std::nullptr_t) noexcept;
```
[none]
* {blank}
+
Effects:: Constructs an empty `local_shared_ptr`.
Postconditions:: `local_use_count() == 0 && get() == 0`.
### pointer constructor
```
template<class Y> explicit local_shared_ptr(Y * p);
```
[none]
* {blank}
+
Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p )`.
Postconditions:: `local_use_count() == 1 && get() == p`.
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
### constructors taking a deleter
```
template<class Y, class D> local_shared_ptr(Y * p, D d);
```
```
template<class D> local_shared_ptr(std::nullptr_t p, D d);
```
[none]
* {blank}
+
Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p, d )`.
Postconditions:: `local_use_count() == 1 && get() == p`.
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
```
template<class Y, class D, class A> local_shared_ptr(Y * p, D d, A a);
```
```
template<class D, class A> local_shared_ptr(std::nullptr_t p, D d, A a);
```
[none]
* {blank}
+
Effects:: Constructs a `local_shared_ptr` that owns `shared_ptr<T>( p, d, a )`.
Postconditions:: `local_use_count() == 1 && get() == p`.
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
### copy and converting constructors
```
local_shared_ptr(local_shared_ptr const & r) noexcept;
```
```
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r) noexcept;
```
[none]
* {blank}
+
Requires:: `Y*` should be convertible to `T*`.
Effects:: If `r` is empty, constructs an empty `local_shared_ptr`; otherwise, constructs a `local_shared_ptr` that shares ownership with `r`.
Postconditions:: `get() == r.get() && local_use_count() == r.local_use_count()`.
### move constructors
```
local_shared_ptr(local_shared_ptr && r) noexcept;
```
```
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r) noexcept;
```
[none]
* {blank}
+
Requires:: `Y*` should be convertible to `T*`.
Effects:: Move-constructs a `local_shared_ptr` from `r`.
Postconditions:: `*this` contains the old value of `r`. `r` is empty and `r.get() == 0`.
### shared_ptr constructor
```
template<class Y> local_shared_ptr( shared_ptr<Y> const & r );
```
```
template<class Y> local_shared_ptr( shared_ptr<Y> && r );
```
[none]
* {blank}
+
Effects:: Constructs a `local_shared_ptr` that owns `r`.
Postconditions:: `local_use_count() == 1`. `get()` returns the old value of `r.get()`.
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
### aliasing constructor
```
template<class Y> local_shared_ptr(local_shared_ptr<Y> const & r, element_type * p) noexcept;
```
[none]
* {blank}
+
Effects:: constructs a `local_shared_ptr` that shares ownership with `r` and stores `p`.
Postconditions:: `get() == p && local_use_count() == r.local_use_count()`.
### aliasing move constructor
```
template<class Y> local_shared_ptr(local_shared_ptr<Y> && r, element_type * p) noexcept;
```
[none]
* {blank}
+
Effects:: Move-constructs a `local_shared_ptr` from `r`, while storing `p` instead.
Postconditions:: `get() == p` and `local_use_count()` equals the old count of `r`. `r` is empty and `r.get() == 0`.
### unique_ptr constructor
```
template<class Y, class D> local_shared_ptr(std::unique_ptr<Y, D> && r);
```
[none]
* {blank}
+
Requires:: `Y*` should be convertible to `T*`.
Effects::
- When `r.get() == 0`, equivalent to `local_shared_ptr()`;
- Otherwise, constructs a `local_shared_ptr` that owns `shared_ptr<T>( std::move(r) )`.
Throws:: `std::bad_alloc`, or an implementation-defined exception when a resource other than memory could not be obtained.
Exception safety:: If an exception is thrown, the constructor has no effect.
### destructor
```
~local_shared_ptr() noexcept;
```
[none]
* {blank}
+
Effects::
- If `*this` is empty, or shares ownership with another `local_shared_ptr` instance (`local_use_count() > 1`), there are no side effects.
- Otherwise, destroys the owned `shared_ptr`.
### assignment
```
local_shared_ptr & operator=(local_shared_ptr const & r) noexcept;
```
```
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> const & r) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(r).swap(*this)`.
Returns:: `*this`.
```
local_shared_ptr & operator=(local_shared_ptr && r) noexcept;
```
```
template<class Y> local_shared_ptr & operator=(local_shared_ptr<Y> && r) noexcept;
```
```
template<class Y, class D> local_shared_ptr & operator=(std::unique_ptr<Y, D> && r);
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(std::move(r)).swap(*this)`.
Returns:: `*this`.
```
local_shared_ptr & operator=(std::nullptr_t) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr().swap(*this)`.
Returns:: `*this`.
### reset
```
void reset() noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr().swap(*this)`.
```
template<class Y> void reset(Y * p);
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(p).swap(*this)`.
```
template<class Y, class D> void reset(Y * p, D d);
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(p, d).swap(*this)`.
```
template<class Y, class D, class A> void reset(Y * p, D d, A a);
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(p, d, a).swap(*this)`.
```
template<class Y> void reset(local_shared_ptr<Y> const & r, element_type * p) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(r, p).swap(*this)`.
```
template<class Y> void reset(local_shared_ptr<Y> && r, element_type * p) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `local_shared_ptr(std::move(r), p).swap(*this)`.
### indirection
```
T & operator*() const noexcept;
```
[none]
* {blank}
+
Requires:: `T` should not be an array type.
Returns:: `*get()`.
```
T * operator->() const noexcept;
```
[none]
* {blank}
+
Requires:: `T` should not be an array type.
Returns:: `get()`.
```
element_type & operator[](std::ptrdiff_t i) const noexcept;
```
[none]
* {blank}
+
Requires:: `T` should be an array type. The stored pointer must not be 0. `i >= 0`. If `T` is `U[N]`, `i < N`.
Returns:: `get()[i]`.
### get
```
element_type * get() const noexcept;
```
[none]
* {blank}
+
Returns:: The stored pointer.
### local_use_count
```
long local_use_count() const noexcept;
```
[none]
* {blank}
+
Returns:: The number of `local_shared_ptr` objects, `*this` included, that share ownership with `*this`, or 0 when `*this` is empty.
### conversions
```
explicit operator bool() const noexcept;
```
[none]
* {blank}
+
Returns:: `get() != 0`.
NOTE: On C++03 compilers, the return value is of an unspecified type.
```
template<class Y> operator shared_ptr<Y>() const noexcept;
```
```
template<class Y> operator weak_ptr<Y>() const noexcept;
```
[none]
* {blank}
+
Requires:: `T*` should be convertible to `Y*`.
Returns:: a copy of the owned `shared_ptr`.
### swap
```
void swap(local_shared_ptr & b) noexcept;
```
[none]
* {blank}
+
Effects:: Exchanges the contents of the two smart pointers.
### owner_before
```
template<class Y> bool owner_before(local_shared_ptr<Y> const & rhs) const noexcept;
```
[none]
* {blank}
+
Effects:: See the description of `operator<`.
## Free Functions
### comparison
```
template<class T, class U>
bool operator==(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
```
```
template<class T, class U>
bool operator==(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
```
```
template<class T, class U>
bool operator==(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: `a.get() == b.get()`.
```
template<class T, class U>
bool operator!=(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
```
```
template<class T, class U>
bool operator!=(local_shared_ptr<T> const & a, shared_ptr<U> const & b) noexcept;
```
```
template<class T, class U>
bool operator!=(shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: `a.get() != b.get()`.
```
template<class T> bool operator==(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
```
```
template<class T> bool operator==(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
```
[none]
* {blank}
+
Returns:: `p.get() == 0`.
```
template<class T> bool operator!=(local_shared_ptr<T> const & p, std::nullptr_t) noexcept;
```
```
template<class T> bool operator!=(std::nullptr_t, local_shared_ptr<T> const & p) noexcept;
```
[none]
* {blank}
+
Returns:: `p.get() != 0`.
```
template<class T, class U>
bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: An unspecified value such that
- `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard;
- under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `local_shared_ptr` instances
are equivalent if and only if they share ownership or are both empty.
NOTE: Allows `local_shared_ptr` objects to be used as keys in associative containers.
NOTE: The rest of the comparison operators are omitted by design.
### swap
```
template<class T> void swap(local_shared_ptr<T> & a, local_shared_ptr<T> & b) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `a.swap(b)`.
### get_pointer
```
template<class T>
typename local_shared_ptr<T>::element_type *
get_pointer(local_shared_ptr<T> const & p) noexcept;
```
[none]
* {blank}
+
Returns:: `p.get()`.
NOTE: Provided as an aid to generic programming. Used by `mem_fn`.
### static_pointer_cast
```
template<class T, class U>
local_shared_ptr<T> static_pointer_cast(local_shared_ptr<U> const & r) noexcept;
```
[none]
* {blank}
+
Requires:: The expression `static_cast<T*>( (U*)0 )` must be well-formed.
Returns:: `local_shared_ptr<T>( r, static_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
CAUTION: The seemingly equivalent expression `local_shared_ptr<T>(static_cast<T*>(r.get()))` will eventually
result in undefined behavior, attempting to delete the same object twice.
### const_pointer_cast
```
template<class T, class U>
local_shared_ptr<T> const_pointer_cast(local_shared_ptr<U> const & r) noexcept;
```
[none]
* {blank}
+
Requires:: The expression `const_cast<T*>( (U*)0 )` must be well-formed.
Returns:: `local_shared_ptr<T>( r, const_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
### dynamic_pointer_cast
```
template<class T, class U>
local_shared_ptr<T> dynamic_pointer_cast(local_shared_ptr<U> const & r) noexcept;
```
[none]
* {blank}
+
Requires:: The expression `dynamic_cast<T*>( (U*)0 )` must be well-formed.
Returns::
- When `dynamic_cast<typename local_shared_ptr<T>::element_type*>(r.get())` returns a nonzero value `p`, `local_shared_ptr<T>(r, p)`;
- Otherwise, `local_shared_ptr<T>()`.
### reinterpret_pointer_cast
```
template<class T, class U>
local_shared_ptr<T> reinterpret_pointer_cast(local_shared_ptr<U> const & r) noexcept;
```
[none]
* {blank}
+
Requires:: The expression `reinterpret_cast<T*>( (U*)0 )` must be well-formed.
Returns:: `local_shared_ptr<T>( r, reinterpret_cast<typename local_shared_ptr<T>::element_type*>(r.get()) )`.
### operator<<
```
template<class E, class T, class Y>
std::basic_ostream<E, T> &
operator<< (std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p);
```
[none]
* {blank}
+
Effects:: `os << p.get();`.
Returns:: `os`.
### get_deleter
```
template<class D, class T>
D * get_deleter(local_shared_ptr<T> const & p) noexcept;
```
[none]
* {blank}
+
Returns:: If `*this` owns a `shared_ptr` instance `p`, `get_deleter<D>( p )`, otherwise 0.

View File

@@ -0,0 +1,81 @@
////
Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
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
////
[#make_local_shared]
# make_local_shared: Creating local_shared_ptr
:toc:
:toc-title:
:idprefix: make_local_shared_
## Description
The function templates `make_local_shared` and `allocate_local_shared` provide
convenient, safe and efficient ways to create `local_shared_ptr` objects. They
are analogous to `make_shared` and `allocate_shared` for `shared_ptr`.
## Synopsis
`make_local_shared` and `allocate_local_shared` are defined in
`<boost/smart_ptr/make_local_shared.hpp>`.
[subs=+quotes]
```
namespace boost {
`// T is not an array`
template<class T, class... Args>
local_shared_ptr<T> make_local_shared(Args&&... args);
template<class T, class A, class... Args>
local_shared_ptr<T> allocate_local_shared(const A& a, Args&&... args);
`// T is an array of unknown bounds`
template<class T>
local_shared_ptr<T> make_local_shared(std::size_t n);
template<class T, class A>
local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n);
`// T is an array of known bounds`
template<class T>
local_shared_ptr<T> make_local_shared();
template<class T, class A>
local_shared_ptr<T> allocate_local_shared(const A& a);
`// T is an array of unknown bounds`
template<class T>
local_shared_ptr<T> make_local_shared(std::size_t n,
const remove_extent_t<T>& v);
template<class T, class A>
local_shared_ptr<T> allocate_local_shared(const A& a, std::size_t n,
const remove_extent_t<T>& v);
`// T is an array of known bounds`
template<class T>
local_shared_ptr<T> make_local_shared(const remove_extent_t<T>& v);
template<class T, class A>
local_shared_ptr<T> allocate_local_shared(const A& a,
const remove_extent_t<T>& v);
`// T is not an array of known bounds`
template<class T>
local_shared_ptr<T> make_local_shared_noinit();
template<class T, class A>
local_shared_ptr<T> allocate_local_shared_noinit(const A& a);
`// T is an array of unknown bounds`
template<class T>
local_shared_ptr<T> make_local_shared_noinit(std::size_t n);
template<class T, class A>
local_shared_ptr<T> allocate_local_shared_noinit(const A& a,
std::size_t n);
}
```
## Description
The requirements and effects of these functions are the same as `make_shared`
and `allocate_shared`, except that a `local_shared_ptr` is returned.

View File

@@ -0,0 +1,296 @@
////
Copyright 2017 Peter Dimov
Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
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
////
[#make_shared]
# make_shared: Creating shared_ptr
:toc:
:toc-title:
:idprefix: make_shared_
## Description
The function templates `make_shared` and `allocate_shared` provide convenient,
safe and efficient ways to create `shared_ptr` objects.
## Rationale
Consistent use of `shared_ptr` can eliminate the need to use an explicit
`delete`, but alone it provides no support in avoiding explicit `new`. There
were repeated requests from users for a factory function that creates an
object of a given type and returns a `shared_ptr` 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
`shared_ptr` construction overhead. This eliminates one of the major
efficiency complaints about `shared_ptr`.
The family of overloaded function templates, `make_shared` and
`allocate_shared`, were provided to address this need. `make_shared` uses the
global `operator new` to allocate memory, whereas `allocate_shared` uses an
user-supplied allocator, allowing finer control.
The rationale for choosing the name `make_shared` is that the expression
`make_shared<Widget>()` can be read aloud and conveys the intended meaning.
Originally the Boost function templates `allocate_shared` and `make_shared`
were provided for scalar objects only. There was a need to have efficient
allocation of array objects. One criticism of class template `shared_array`
was always the lack of a utility like `make_shared` that uses only a single
allocation. When `shared_ptr` was enhanced to support array types, additional
overloads of `allocate_shared` and `make_shared` were provided for array
types.
## Synopsis
`make_shared` and `allocate_shared` are defined in
`<boost/smart_ptr/make_shared.hpp>`.
[subs=+quotes]
```
namespace boost {
`// T is not an array`
template<class T, class... Args>
shared_ptr<T> make_shared(Args&&... args);
template<class T, class A, class... Args>
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
`// T is an array of unknown bounds`
template<class T>
shared_ptr<T> make_shared(std::size_t n);
template<class T, class A>
shared_ptr<T> allocate_shared(const A& a, std::size_t n);
`// T is an array of known bounds`
template<class T>
shared_ptr<T> make_shared();
template<class T, class A>
shared_ptr<T> allocate_shared(const A& a);
`// T is an array of unknown bounds`
template<class T> shared_ptr<T>
make_shared(std::size_t n, const remove_extent_t<T>& v);
template<class T, class A> shared_ptr<T>
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
`// T is an array of known bounds`
template<class T>
shared_ptr<T> make_shared(const remove_extent_t<T>& v);
template<class T, class A>
shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
`// T is not an array of unknown bounds`
template<class T>
shared_ptr<T> make_shared_noinit();
template<class T, class A>
shared_ptr<T> allocate_shared_noinit(const A& a);
`// T is an array of unknown bounds`
template<class T>
shared_ptr<T> make_shared_noinit(std::size_t n);
template<class T, class A>
shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
}
```
## Common Requirements
The common requirements that apply to all `make_shared` and `allocate_shared`
overloads, unless specified otherwise, are described below.
Requires:: `A` shall be an _allocator_. The copy constructor and destructor
of `A` shall not throw exceptions.
Effects:: Allocates memory for an object of type `T` or `n` objects of `U`
(if `T` is an array type of the form `U[]` and `n` is determined by
arguments, as specified by the concrete overload). The object is initialized
from arguments as specified by the concrete overload. Uses a rebound copy of
`a` (for an unspecified `value_type`) to allocate memory. If an exception is
thrown, the functions have no effect.
Returns:: A `shared_ptr` instance that stores and owns the address of the
newly constructed object.
Postconditions:: `r.get() != 0` and `r.use_count() == 1`, where `r`
is the return value.
Throws:: `std::bad_alloc`, an exception thrown from `A::allocate`, or from the
initialization of the object.
Remarks::
* Performs no more than one memory allocation. This provides efficiency
equivalent to an intrusive smart pointer.
* When an object of an array type is specified to be initialized to a value of
the same type `v`, this shall be interpreted to mean that each array element
of the object is initialized to the corresponding element from `v`.
* When an object of an array type is specified to be value-initialized, this
shall be interpreted to mean that each array element of the object is
value-initialized.
* When a (sub)object of non-array type `U` is specified to be initialized to
a value `v`, or constructed from `args\...`, `make_shared` shall perform
this initialization via the expression `::new(p) U(expr)` (where
`_expr_` is `v` or `std::forward<Args>(args)\...)` respectively) and `p`
has type `void*` and points to storage suitable to hold an object of type
`U`.
* When a (sub)object of non-array type `U` is specified to be initialized to
a value `v`, or constructed from `args\...`, `allocate_shared` shall
perform this initialization via the expression
`std::allocator_traits<A2>::construct(a2, p, expr)` (where
`_expr_` is `v` or `std::forward<Args>(args)\...)` respectively), `p`
points to storage suitable to hold an object of type `U`, and `a2` of
type `A2` is a potentially rebound copy of `a`.
* When a (sub)object of non-array type `U` is specified to be
default-initialized, `make_shared_noinit` and `allocate_shared_noinit` shall
perform this initialization via the expression `::new(p) U`, where
`p` has type `void*` and points to storage suitable to hold an object of
type `U`.
* When a (sub)object of non-array type `U` is specified to be
value-initialized, `make_shared` shall perform this initialization via the
expression `::new(p) U()`, where `p` has type `void*` and points to
storage suitable to hold an object of type `U`.
* When a (sub)object of non-array type `U` is specified to be
value-initialized, `allocate_shared` shall perform this initialization via the
expression `std::allocator_traits<A2>::construct(a2, p)`, where
`p` points to storage suitable to hold an object of type `U` and `a2` of
type `A2` is a potentially rebound copy of `a`.
* Array elements are initialized in ascending order of their addresses.
* When the lifetime of the object managed by the return value ends, or when
the initialization of an array element throws an exception, the initialized
elements should be destroyed in the reverse order of their construction.
NOTE: These functions will typically allocate more memory than the total size
of the element objects to allow for internal bookkeeping structures such as
the reference counts.
## Free Functions
```
template<class T, class... Args>
shared_ptr<T> make_shared(Args&&... args);
```
```
template<class T, class A, class... Args>
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
```
[none]
* {blank}
+
Constraints:: `T` is not an array.
Returns:: A `shared_ptr` to an object of type `T`, constructed from
`args\...`.
Examples::
* `auto p = make_shared<int>();`
* `auto p = make_shared<std::vector<int> >(16, 1);`
```
template<class T>
shared_ptr<T> make_shared(std::size_t n);
```
```
template<class T, class A>
shared_ptr<T> allocate_shared(const A& a, std::size_t n);
```
[none]
* {blank}
+
Constraints:: `T` is an array of unknown bounds.
Returns:: A `shared_ptr` to a sequence of `n` value-initialized objects of
type `remove_extent_t<T>`.
Examples::
* `auto p = make_shared<double[]>(1024);`
* `auto p = make_shared<double[][2][2]>(6);`
```
template<class T>
shared_ptr<T> make_shared();
```
```
template<class T, class A>
shared_ptr<T> allocate_shared(const A& a);
```
[none]
* {blank}
+
Constraints:: `T` is an array of known bounds.
Returns:: A `shared_ptr` to a sequence of `extent_v<T>` value-initialized
objects of type `remove_extent_t<T>`.
Examples::
* `auto p = make_shared<double[1024]>();`
* `auto p = make_shared<double[6][2][2]>();`
```
template<class T> shared_ptr<T>
make_shared(std::size_t n, const remove_extent_t<T>& v);
```
```
template<class T, class A> shared_ptr<T>
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
```
[none]
* {blank}
+
Constraints:: `T` is an array of unknown bounds.
Returns:: A `shared_ptr` to a sequence of `n` objects of type
`remove_extent_t<T>`, each initialized to `v`.
Examples::
* `auto p = make_shared<double[]>(1024, 1.0);`
* `auto p = make_shared<double[][2]>(6, {1.0, 0.0});`
* `auto p = make_shared<std::vector<int>[]>(4, {1, 2});`
```
template<class T>
shared_ptr<T> make_shared(const remove_extent_t<T>& v);
```
```
template<class T, class A>
shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
```
[none]
* {blank}
+
Constraints:: `T` is an array of known bounds.
Returns:: A `shared_ptr` to a sequence of `extent_v<T>` objects of type
`remove_extent_t<T>`, each initialized to `v`.
Examples::
* `auto p = make_shared<double[1024]>(1.0);`
* `auto p = make_shared<double[6][2]>({1.0, 0.0});`
* `auto p = make_shared<std::vector<int>[4]>({1, 2});`
```
template<class T>
shared_ptr<T> make_shared_noinit();
```
```
template<class T, class A>
shared_ptr<T> allocate_shared_noinit(const A& a);
```
[none]
* {blank}
+
Constraints:: `T` is not an array, or is an array of known bounds.
Returns:: A `shared_ptr` to a default-initialized object of type `T`, or a
sequence of `extent_v<T>` default-initialized objects of type
`remove_extent_t<T>`, respectively.
Example:: `auto p = make_shared_noinit<double[1024]>();`
```
template<class T>
shared_ptr<T> make_shared_noinit(std::size_t n);
```
```
template<class T, class A>
shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
```
[none]
* {blank}
+
Constraints:: `T` is an array of unknown bounds.
Returns:: A `shared_ptr` to a sequence of `_n_` default-initialized objects
of type `remove_extent_t<T>`.
Example:: `auto p = make_shared_noinit<double[]>(1024);`

View File

@@ -0,0 +1,120 @@
////
Copyright 2017 Peter Dimov
Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
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
////
[#make_unique]
# make_unique: Creating unique_ptr
:toc:
:toc-title:
:idprefix: make_unique_
## Description
The `make_unique` function templates provide convenient and safe ways to
create `std::unique_ptr` objects.
## Rationale
The {cpp}11 standard introduced `std::unique_ptr` but did not provide any
`make_unique` utility like `std::make_shared` that provided the same
exception safety and facility to avoid writing `new` expressions. Before it
was implemented by some standard library vendors (and prior to the {cpp}14
standard introducing `std::make_unique`), this library provided it due to
requests from users.
This library also provides additional overloads of `make_unique` for
default-initialization, when users do not need or want to incur the expense
of value-initialization. The {cpp} standard does not yet provide this
feature with `std::make_unique`.
## Synopsis
`make_unique` is defined in `<boost/smart_ptr/make_unique.hpp>`.
[subs=+quotes]
```
namespace boost {
`// T is not an array`
template<class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args);
`// T is not an array`
template<class T>
std::unique_ptr<T> make_unique(type_identity_t<T>&& v);
`// T is an array of unknown bounds`
template<class T>
std::unique_ptr<T> make_unique(std::size_t n);
`// T is not an array`
template<class T>
std::unique_ptr<T> make_unique_noinit();
`// T is an array of unknown bounds`
template<class T>
std::unique_ptr<T> make_unique_noinit(std::size_t n);
}
```
## Free Functions
```
template<class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args);
```
[none]
* {blank}
+
Constraints:: `T` is not an array.
Returns:: `std::unique_ptr<T>(new T(std::forward<Args>(args)\...)`.
Example:: `auto p = make_unique<int>();`
```
template<class T>
std::unique_ptr<T> make_unique(type_identity_t<T>&& v);
```
[none]
* {blank}
+
Constraints:: `T` is not an array.
Returns:: `std::unique_ptr<T>(new T(std::move(v))`.
Example:: `auto p = make_unique<std::vector<int> >({1, 2});`
```
template<class T>
std::unique_ptr<T> make_unique(std::size_t n);
```
[none]
* {blank}
+
Constraints:: `T` is an array of unknown bounds.
Returns:: `std::unique_ptr<T>(new remove_extent_t<T>[n]())`.
Example:: `auto p = make_unique<double[]>(1024);`
```
template<class T>
std::unique_ptr<T> make_unique_noinit();
```
[none]
* {blank}
+
Constraints:: `T` is not an array.
Returns:: `std::unique_ptr<T>(new T)`.
Example:: `auto p = make_unique_noinit<double[1024]>();`
```
template<class T>
std::unique_ptr<T> make_unique_noinit(std::size_t n);
```
[none]
* {blank}
+
Constraints:: `T` is an array of unknown bounds.
Returns:: `std::unique_ptr<T>(new remove_extent_t<T>[n])`.
Example:: `auto p = make_unique_noinit<double[]>(1024);`

View File

@@ -0,0 +1,237 @@
////
Copyright 2017 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
////
[#pointer_cast]
# Generic Pointer Casts
:toc:
:toc-title:
:idprefix: pointer_cast_
## Description
The pointer cast function templates (`static_pointer_cast`,
`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast`)
provide a way to write generic pointer castings for raw pointers,
`std::shared_ptr` and `std::unique_ptr`.
There is test and example code in
link:../../test/pointer_cast_test.cpp[pointer_cast_test.cpp]
## Rationale
Boost smart pointers usually overload those functions to provide a mechanism
to emulate pointers casts. For example, `shared_ptr<T>` implements a static
pointer cast this way:
```
template<class T, class U>
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& p);
```
Pointer cast functions templates are overloads of `static_pointer_cast`,
`dynamic_pointer_cast`, `const_pointer_cast`, and `reinterpret_pointer_cast`
for raw pointers, `std::shared_ptr` and `std::unique_ptr`. 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.
## Synopsis
The generic pointer casts are defined in `<boost/pointer_cast.hpp>`.
```
namespace boost {
template<class T, class U> T* static_pointer_cast(U* p) noexcept;
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
template<class T, class U> T* const_pointer_cast(U* p) noexcept;
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
template<class T, class U> std::shared_ptr<T>
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
template<class T, class U> std::shared_ptr<T>
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
template<class T, class U> std::shared_ptr<T>
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
template<class T, class U> std::shared_ptr<T>
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
template<class T, class U> std::unique_ptr<T>
static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
template<class T, class U> std::unique_ptr<T>
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
template<class T, class U> std::unique_ptr<T>
const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
template<class T, class U> std::unique_ptr<T>
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
}
```
## Free Functions
### static_pointer_cast
```
template<class T, class U> T* static_pointer_cast(U* p) noexcept;
```
[none]
* {blank}
+
Returns:: `static_cast<T*>(p)`
```
template<class T, class U> std::shared_ptr<T>
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
```
[none]
* {blank}
+
Returns:: `std::static_pointer_cast<T>(p)`
```
template<class T, class U> std::unique_ptr<T>
static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
```
[none]
* {blank}
+
Requires:: The expression `static_cast<T*>((U*)0)` must be well-formed.
Returns:: `std::unique_ptr<T>(static_cast<typename
std::unique_ptr<T>::element_type*>(p.release()))`.
CAUTION: The seemingly equivalent expression
`std::unique_ptr<T>(static_cast<T*>(p.get()))` will eventually result in
undefined behavior, attempting to delete the same object twice.
### dynamic_pointer_cast
```
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
```
[none]
* {blank}
+
Returns:: `dynamic_cast<T*>(p)`
```
template<class T, class U> std::shared_ptr<T>
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
```
[none]
* {blank}
+
Returns:: `std::dynamic_pointer_cast<T>(p)`
```
template<class T, class U> std::unique_ptr<T>
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
```
[none]
* {blank}
+
Requires::
* The expression `static_cast<T*>((U*)0)` must be well-formed.
* `T` must have a virtual destructor.
Returns::
* When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())`
returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename
std::unique_ptr<T>::element_type*>(p.release()));`.
* Otherwise, `std::unique_ptr<T>()`.
### const_pointer_cast
```
template<class T, class U> T* const_pointer_cast(U* p) noexcept;
```
[none]
* {blank}
+
Returns:: `const_cast<T*>(p)`
```
template<class T, class U> std::shared_ptr<T>
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
```
[none]
* {blank}
+
Returns:: `std::const_pointer_cast<T>(p)`
```
template<class T, class U> std::unique_ptr<T>
const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
```
[none]
* {blank}
+
Requires:: The expression `const_cast<T*>((U*)0)` must be well-formed.
Returns:: `std::unique_ptr<T>(const_cast<typename
std::unique_ptr<T>::element_type*>(p.release()))`.
### reinterpret_pointer_cast
```
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
```
[none]
* {blank}
+
Returns:: `reinterpret_cast<T*>(p)`
```
template<class T, class U> std::shared_ptr<T>
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
```
[none]
* {blank}
+
Returns:: `std::reinterpret_pointer_cast<T>(p)`
```
template<class T, class U> std::unique_ptr<T>
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
```
[none]
* {blank}
+
Requires:: The expression `reinterpret_cast<T*>((U*)0)` must be well-formed.
Returns:: `std::unique_ptr<T>(reinterpret_cast<typename
std::unique_ptr<T>::element_type*>(p.release()))`.
## Example
The following example demonstrates how the generic pointer casts help us
create pointer independent code.
```
#include <boost/pointer_cast.hpp>
#include <boost/shared_ptr.hpp>
class base {
public:
virtual ~base() { }
};
class derived : public base { };
template<class Ptr>
void check_if_it_is_derived(const Ptr& ptr)
{
assert(boost::dynamic_pointer_cast<derived>(ptr) != 0);
}
int main()
{
base* ptr = new derived;
boost::shared_ptr<base> sptr(new derived);
check_if_it_is_derived(ptr);
check_if_it_is_derived(sptr);
delete ptr;
}
```

View File

@@ -0,0 +1,114 @@
////
Copyright 2005, 2006 Ion Gaztañaga
Copyright 2005, 2006, 2017 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
////
[#pointer_to_other]
# pointer_to_other
:toc:
:toc-title:
:idprefix: pointer_to_other_
## Description
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.
There is test/example code in link:../../test/pointer_to_other_test.cpp[pointer_to_other_test.cpp].
## Rationale
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`.)
```
template <class IntPtr> class FloatPointerHolder
{
// Let's define a pointer to a float
typedef typename boost::pointer_to_other
<IntPtr, float>::type float_ptr_t;
float_ptr_t float_ptr;
};
```
## Synopsis
`pointer_to_other` is defined in `<boost/smart_ptr/pointer_to_other.hpp>`.
```
namespace boost {
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;
};
}
```
If these definitions are not correct for a specific smart pointer, we can define a specialization of `pointer_to_other`.
## Example
```
// Let's define a memory allocator that can
// work with raw and smart pointers
#include <boost/pointer_to_other.hpp>
template <class VoidPtr>
class memory_allocator
{
// Predefine a memory_block
struct block;
// 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<void>, block_ptr_t is smart_ptr<block>
typedef typename boost::pointer_to_other
<VoidPtr, block>::type block_ptr_t;
struct block
{
std::size_t size;
block_ptr_t next_block;
};
block_ptr_t free_blocks;
};
```
As we can see, using `pointer_to_other` we can create pointer independent code.

View File

@@ -0,0 +1,175 @@
////
Copyright 1999 Greg Colvin and Beman Dawes
Copyright 2002 Darin Adler
Copyright 2002-2005, 2017 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
////
[#scoped_array]
# scoped_array: Scoped Array Ownership
:toc:
:toc-title:
:idprefix: scoped_array_
## Description
The `scoped_array` class template stores a pointer to a dynamically allocated array.
(Dynamically allocated arrays are allocated with the {cpp} `new[]` expression.) The array
pointed to is guaranteed to be deleted, either on destruction of the `scoped_array`,
or via an explicit `reset`.
The `scoped_array` 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 noncopyable) signal its intent to retain ownership solely within the current scope.
Because it is noncopyable, it is safer than `shared_ptr<T[]>` for pointers which should not be copied.
Because `scoped_array` 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.
It cannot be used in {cpp} standard library containers. See `shared_ptr<T[]>` if `scoped_array`
does not meet your needs.
It cannot correctly hold a pointer to a single object. See `scoped_ptr` for that usage.
`std::vector` is an alternative to `scoped_array` that is a bit heavier duty but far more flexible.
`boost::array` is an alternative that does not use dynamic allocation.
The class template is parameterized on `T`, the type of the object pointed to.
## Synopsis
`scoped_array` is defined in `<boost/smart_ptr/scoped_array.hpp>`.
```
namespace boost {
template<class T> class scoped_array {
private:
scoped_array(scoped_array const &);
scoped_array & operator=(scoped_array const &);
void operator==( scoped_array const& ) const;
void operator!=( scoped_array const& ) const;
public:
typedef T element_type;
explicit scoped_array(T * p = 0) noexcept;
~scoped_array() noexcept;
void reset(T * p = 0) noexcept;
T & operator[](std::ptrdiff_t i) const noexcept;
T * get() const noexcept;
explicit operator bool () const noexcept;
void swap(scoped_array & b) noexcept;
};
template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept;
template<class T>
bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept;
template<class T>
bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept;
template<class T>
bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept;
template<class T>
bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept;
}
```
## Members
### element_type
typedef T element_type;
Provides the type of the stored pointer.
### constructors
explicit scoped_array(T * p = 0) noexcept;
Constructs a `scoped_array`, storing a copy of `p`, which must have been
allocated via a {cpp} `new[]` expression or be 0. `T` is not required be a complete type.
### destructor
~scoped_array() noexcept;
Deletes the array pointed to by the stored pointer. Note that `delete[]` on a pointer with
a value of 0 is harmless. `T` must be complete, and `delete[]` on the stored pointer must
not throw exceptions.
### reset
void reset(T * p = 0) noexcept;
Deletes the array pointed to by the stored pointer and then stores a copy of `p`,
which must have been allocated via a {cpp} `new[]` expression or be 0. `T` must be complete,
and `delete[]` on the stored pointer must not throw exceptions.
### subscripting
T & operator[](std::ptrdiff_t i) const noexcept;
Returns a reference to element `i` of the array pointed to by the stored pointer.
Behavior is undefined and almost certainly undesirable if the stored pointer is 0,
or if `i` is less than 0 or is greater than or equal to the number of elements in
the array.
### get
T * get() const noexcept;
Returns the stored pointer. `T` need not be a complete type.
### conversions
explicit operator bool () const noexcept;
Returns `get() != 0`.
NOTE: On C++03 compilers, the return value is of an unspecified type.
### swap
void swap(scoped_array & b) noexcept;
Exchanges the contents of the two smart pointers. `T` need not be a complete type.
## Free Functions
### swap
template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b) noexcept;
Equivalent to `a.swap(b)`.
### comparisons
template<class T>
bool operator==( scoped_array<T> const & p, std::nullptr_t ) noexcept;
template<class T>
bool operator==( std::nullptr_t, scoped_array<T> const & p ) noexcept;
Returns `p.get() == nullptr`.
template<class T>
bool operator!=( scoped_array<T> const & p, std::nullptr_t ) noexcept;
template<class T>
bool operator!=( std::nullptr_t, scoped_array<T> const & p ) noexcept;
Returns `p.get() != nullptr`.

View File

@@ -0,0 +1,234 @@
////
Copyright 2017 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
////
[#scoped_ptr]
# scoped_ptr: Scoped Object Ownership
:toc:
:toc-title:
:idprefix: scoped_ptr_
## Description
The `scoped_ptr` class template stores a pointer to a dynamically allocated object.
(Dynamically allocated objects are allocated with the {cpp} `new` expression.) The
object pointed to is guaranteed to be deleted, either on destruction of the `scoped_ptr`,
or via an explicit `reset`. See the <<scoped_ptr_example,example>>.
`scoped_ptr` 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 noncopyable) signal its intent to retain
ownership solely within the current scope. Because it is noncopyable, it is safer than `shared_ptr`
for pointers which should not be copied.
Because `scoped_ptr` 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.
`scoped_ptr` cannot be used in {cpp} Standard Library containers. Use `shared_ptr` or `std::unique_ptr`
if you need a smart pointer that can.
`scoped_ptr` cannot correctly hold a pointer to a dynamically allocated array. See `scoped_array` for that usage.
The class template is parameterized on `T`, the type of the object pointed to. Destroying `T` must not thow exceptions,
and `T` must be complete at the point `scoped_ptr<T>::~scoped_ptr` is instantiated.
## Synopsis
`scoped_ptr` is defined in `<boost/smart_ptr/scoped_ptr.hpp>`.
```
namespace boost {
template<class T> class scoped_ptr {
private:
scoped_ptr(scoped_ptr const&);
scoped_ptr& operator=(scoped_ptr const&);
void operator==(scoped_ptr const&) const;
void operator!=(scoped_ptr const&) const;
public:
typedef T element_type;
explicit scoped_ptr(T * p = 0) noexcept;
~scoped_ptr() noexcept;
void reset(T * p = 0) noexcept;
T & operator*() const noexcept;
T * operator->() const noexcept;
T * get() const noexcept;
explicit operator bool() const noexcept;
void swap(scoped_ptr & b) noexcept;
};
template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;
template<class T>
bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
template<class T>
bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
template<class T>
bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
template<class T>
bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
}
```
## Members
### element_type
typedef T element_type;
Provides the type of the stored pointer.
### constructor
explicit scoped_ptr(T * p = 0) noexcept;
Constructs a `scoped_ptr`, storing a copy of `p`, which must have been allocated via a
{cpp} `new` expression or be 0. `T` is not required be a complete type.
### destructor
~scoped_ptr() noexcept;
Destroys the object pointed to by the stored pointer, if any, as if by using
`delete this\->get()`. `T` must be a complete type.
### reset
void reset(T * p = 0) noexcept;
Deletes the object pointed to by the stored pointer and then stores a copy of
`p`, which must have been allocated via a {cpp} `new` expression or be 0.
Since the previous object needs to be deleted, `T` must be a complete type.
### indirection
T & operator*() const noexcept;
Returns a reference to the object pointed to by the stored pointer. Behavior is undefined if the stored pointer is 0.
T * operator->() const noexcept;
Returns the stored pointer. Behavior is undefined if the stored pointer is 0.
### get
T * get() const noexcept;
Returns the stored pointer. `T` need not be a complete type.
### conversions
explicit operator bool () const noexcept; // never throws
Returns `get() != 0`.
NOTE: On C++03 compilers, the return value is of an unspecified type.
### swap
void swap(scoped_ptr & b) noexcept;
Exchanges the contents of the two smart pointers. `T` need not be a complete type.
## Free Functions
### swap
template<class T> void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) noexcept;
Equivalent to `a.swap(b)`.
### comparisons
template<class T> bool operator==( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
template<class T> bool operator==( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
Returns `p.get() == nullptr`.
template<class T> bool operator!=( scoped_ptr<T> const & p, std::nullptr_t ) noexcept;
template<class T> bool operator!=( std::nullptr_t, scoped_ptr<T> const & p ) noexcept;
Returns `p.get() != nullptr`.
## Example
Here's an example that uses `scoped_ptr`.
```
#include <boost/scoped_ptr.hpp>
#include <iostream>
struct Shoe { ~Shoe() { std::cout << "Buckle my shoe\n"; } };
class MyClass {
boost::scoped_ptr<int> ptr;
public:
MyClass() : ptr(new int) { *ptr = 0; }
int add_one() { return ++*ptr; }
};
int main()
{
boost::scoped_ptr<Shoe> x(new Shoe);
MyClass my_instance;
std::cout << my_instance.add_one() << '\n';
std::cout << my_instance.add_one() << '\n';
}
```
The example program produces the beginning of a child's nursery rhyme:
```
1
2
Buckle my shoe
```
## Rationale
The primary reason to use `scoped_ptr` rather than `std::auto_ptr` or `std::unique_ptr` 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.
A secondary reason to use `scoped_ptr` is to prevent a later maintenance programmer from adding a function that transfers
ownership by returning the `auto_ptr`, because the maintenance programmer saw `auto_ptr`, and assumed ownership could safely be transferred.
Think of `bool` vs `int`. We all know that under the covers `bool` is usually just an `int`. Indeed, some argued against including bool in the {cpp}
standard because of that. But by coding `bool` rather than `int`, you tell your readers what your intent is. Same with `scoped_ptr`; by using it you are signaling intent.
It has been suggested that `scoped_ptr<T>` is equivalent to `std::auto_ptr<T> const`. Ed Brey pointed out, however, that `reset` will not work on a `std::auto_ptr<T> const`.
## Handle/Body Idiom
One common usage of `scoped_ptr` is to implement a handle/body (also called pimpl) idiom which avoids exposing the body (implementation) in the header file.
The `link:../../example/scoped_ptr_example_test.cpp[scoped_ptr_example_test.cpp]` sample program includes a header file,
`link:../../example/scoped_ptr_example.hpp[scoped_ptr_example.hpp]`, which uses a `scoped_ptr<>` to an incomplete type to hide the
implementation. The instantiation of member functions which require a complete type occurs in the `link:../../example/scoped_ptr_example.cpp[scoped_ptr_example.cpp]`
implementation file.
## Frequently Asked Questions
[qanda]
Why doesn't `scoped_ptr` have a `release()` member?::
When reading source code, it is valuable to be able to draw conclusions about program behavior based on the types being used. If `scoped_ptr` 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 `std::auto_ptr` where
transfer of ownership is required. (supplied by Dave Abrahams)

View File

@@ -0,0 +1,298 @@
////
Copyright 2017 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
////
[[shared_array]]
[appendix]
# shared_array (deprecated)
:toc:
:toc-title:
:idprefix: shared_array_
NOTE: This facility is deprecated because a `shared_ptr` to `T[]` or `T[N]`
is now available, and is superior in every regard.
## Description
The `shared_array` class template stores a pointer to a dynamically allocated
array. (Dynamically allocated array are allocated with the C++ `new[]`
expression.) The object pointed to is guaranteed to be deleted when the last
`shared_array` pointing to it is destroyed or reset.
Every `shared_array` meets the _CopyConstructible_ and _Assignable_
requirements of the {cpp} Standard Library, and so can be used in standard
library containers. Comparison operators are supplied so that shared_array
works with the standard library's associative containers.
Normally, a `shared_array` cannot correctly hold a pointer to an object that
has been allocated with the non-array form of `new`. See `shared_ptr` for that
usage.
Because the implementation uses reference counting, cycles of `shared_array`
instances will not be reclaimed. For example, if `main` holds a shared_array
to `A`, which directly or indirectly holds a shared_array back to `A`, the use
count of `A` will be 2. Destruction of the original `shared_array` will leave
`A` dangling with a use count of 1.
A `shared_ptr` to a `std::vector` is an alternative to a `shared_array` that
is a bit heavier duty but far more flexible.
The class template is parameterized on `T`, the type of the object pointed to.
`shared_array` and most of its member functions place no requirements on `T`;
it is allowed to be an incomplete type, or `void`. Member functions that do
place additional requirements (constructors, reset) are explicitly documented
below.
## Synopsis
```
namespace boost {
template<class T> class shared_array {
public:
typedef T element_type;
explicit shared_array(T* p = 0);
template<class D> shared_array(T* p, D d);
shared_array(const shared_array& v) noexcept;
~shared_array() noexcept;
shared_array& operator=(const shared_array& v) noexcept;
void reset(T* p = 0);
template<class D> void reset(T* p, D d);
T& operator[](std::ptrdiff_t n) const noexcept;
T* get() const noexcept;
bool unique() const noexcept;
long use_count() const noexcept;
explicit operator bool() const noexcept;
void swap(shared_array<T>& v) noexcept;
};
template<class T> bool
operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept;
template<class T> bool
operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept;
template<class T> bool
operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
template<class T>
void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
}
```
## Members
### element_type
```
typedef T element_type;
```
Type:: Provides the type of the stored pointer.
### Constructors
```
explicit shared_array(T* p = 0);
```
[none]
* {blank}
+
Effects:: Constructs a `shared_array`, storing a copy of `p`, which must be a
pointer to an array that was allocated via a C++ `new[]` expression or be 0.
Afterwards, the use count is 1 (even if `p == 0`; see `~shared_array`).
Requires:: `T` is a complete type.
Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
```
template<class D> shared_array(T* p, D d);
```
[none]
* {blank}
+
Effects:: Constructs a `shared_array`, storing a copy of `p` and of `d`.
Afterwards, the use count is 1. When the the time comes to delete the array
pointed to by `p`, the object `d` is used in the statement `d(p)`.
Requires::
* `T` is a complete type.
* The copy constructor and destructor of `D` must not throw.
* Invoking the object `d` with parameter `p` must not throw.
Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called.
```
shared_array(const shared_array& v) noexcept;
```
[none]
* {blank}
+
Effects:: Constructs a `shared_array`, as if by storing a copy of the pointer
stored in `v`. Afterwards, the use count for all copies is 1 more than the
initial use count.
Requires:: `T` is a complete type.
### Destructor
```
~shared_array() noexcept;
```
[none]
* {blank}
+
Effects:: Decrements the use count. Then, if the use count is 0, deletes the
array pointed to by the stored pointer. Note that `delete[]` on a pointer with
a value of 0 is harmless.
### Assignment
```
shared_array& operator=(const shared_array& v) noexcept;
```
[none]
* {blank}
+
Effects:: Constructs a new `shared_array` as described above, then replaces
this `shared_array` with the new one, destroying the replaced object.
Requires:: `T` is a complete type.
Returns:: `*this`.
### reset
```
void reset(T* p = 0);
```
[none]
* {blank}
+
Effects:: Constructs a new `shared_array` as described above, then replaces
this `shared_array` with the new one, destroying the replaced object.
Requires:: `T` is a complete type.
Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
```
template<class D> void reset(T* p, D d);
```
[none]
* {blank}
+
Effects:: Constructs a new `shared_array` as described above, then replaces
this `shared_array` with the new one, destroying the replaced object.
Requires::
* `T` is a complete type.
* The copy constructor of `D` must not throw.
Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called.
### Indexing
```
T& operator[](std::ptrdiff_t n) const noexcept;
```
Returns:: A reference to element `n` of the array pointed to by the stored
pointer. Behavior is undefined and almost certainly undesirable if the stored
pointer is 0, or if `n` is less than 0 or is greater than or equal to the
number of elements in the array.
Requires:: `T` is a complete type.
### get
```
T* get() const noexcept;
```
[none]
* {blank}
+
Returns:: The stored pointer.
### unique
```
bool unique() const noexcept;
```
[none]
* {blank}
+
Returns:: `true` if no other `shared_array` is sharing ownership of the
stored pointer, `false` otherwise.
### use_count
```
long use_count() const noexcept;
```
[none]
* {blank}
+
Returns:: The number of `shared_array` objects sharing ownership of the
stored pointer.
### Conversions
```
explicit operator bool() const noexcept;
```
[none]
* {blank}
+
Returns:: `get() != 0`.
Requires:: `T` is a complete type.
### swap
```
void swap(shared_array<T>& b) noexcept;
```
[none]
* {blank}
+
Effects:: Exchanges the contents of the two smart pointers.
## Free Functions
### Comparison
```
template<class T> bool
operator==(const shared_array<T>& a, const shared_array<T>& b) noexcept;
```
```
template<class T> bool
operator!=(const shared_array<T>& a, const shared_array<T>& b) noexcept;
```
```
template<class T> bool
operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
```
[none]
* {blank}
+
Returns:: The result of comparing the stored pointers of the two smart
pointers.
NOTE: The `operator<` overload is provided to define an ordering so that
`shared_array` objects can be used in associative containers such as
`std::map`. The implementation uses `std::less<T*>` 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 `std::less` on pointers is well-defined (20.3.3
[lib.comparisons] paragraph 8).
### swap
```
template<class T>
void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
```
[none]
* {blank}
+
Returns:: `a.swap(b)`.
Requires:: `T` is a complete type.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,768 @@
////
Copyright 2003, 2017 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
////
[[techniques]]
[appendix]
# Smart Pointer Programming Techniques
:toc:
:toc-title:
:idprefix: techniques_
[#techniques_incomplete]
## Using incomplete classes for implementation hiding
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:
```
class FILE;
FILE * fopen(char const * name, char const * mode);
void fread(FILE * f, void * data, size_t size);
void fclose(FILE * f);
```
It is possible to express the above interface using `shared_ptr`, eliminating the need to manually call `fclose`:
```
class FILE;
shared_ptr<FILE> fopen(char const * name, char const * mode);
void fread(shared_ptr<FILE> f, void * data, size_t size);
```
This technique relies on `shared_ptr`&#8217;s ability to execute a custom deleter, eliminating the explicit call to `fclose`, and on the fact that `shared_ptr<X>` can be copied and destroyed when `X` is incomplete.
## The "Pimpl" idiom
A {cpp} 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. `shared_ptr` can be used to implement a "Pimpl":
```
// file.hpp:
class file
{
private:
class impl;
shared_ptr<impl> pimpl_;
public:
file(char const * name, char const * mode);
// compiler generated members are fine and useful
void read(void * data, size_t size);
};
// file.cpp:
#include "file.hpp"
class file::impl
{
private:
impl(impl const &);
impl & operator=(impl const &);
// 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_->read(data, size);
}
```
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, `file` is `CopyConstructible` and `Assignable`, allowing its use in standard containers.
## Using abstract classes for implementation hiding
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,
`shared_ptr` can be used as the return type of the factory functions:
```
// X.hpp:
class X
{
public:
virtual void f() = 0;
virtual void g() = 0;
protected:
~X() {}
};
shared_ptr<X> createX();
// X.cpp:
class X_impl: public X
{
private:
X_impl(X_impl const &);
X_impl & operator=(X_impl const &);
public:
virtual void f()
{
// ...
}
virtual void g()
{
// ...
}
};
shared_ptr<X> createX()
{
shared_ptr<X> px(new X_impl);
return px;
}
```
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 `X`; the `shared_ptr<X>` instance returned from `createX` will correctly call `~X_impl`.
## Preventing `delete px.get()`
It is often desirable to prevent client code from deleting a pointer that is being managed by `shared_ptr`. The previous technique showed one possible approach, using a protected destructor. Another alternative is to use a private deleter:
```
class X
{
private:
~X();
class deleter;
friend class deleter;
class deleter
{
public:
void operator()(X * p) { delete p; }
};
public:
static shared_ptr<X> create()
{
shared_ptr<X> px(new X, X::deleter());
return px;
}
};
```
## Encapsulating allocation details, wrapping factory functions
`shared_ptr` can be used in creating {cpp} 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 `CreateX` might allocate `X` from its own private heap, `~X` may
be inaccessible, or `X` may be incomplete:
X * CreateX();
void DestroyX(X *);
The only way to reliably destroy a pointer returned by `CreateX` is to call `DestroyX`.
Here is how a `shared_ptr`-based wrapper may look like:
shared_ptr<X> createX()
{
shared_ptr<X> px(CreateX(), DestroyX);
return px;
}
Client code that calls `createX` still does not need to know how the object has been allocated, but now the destruction is automatic.
[#techniques_static]
## Using a shared_ptr to hold a pointer to a statically allocated object
Sometimes it is desirable to create a `shared_ptr` to an already existing object, so that the `shared_ptr` does not attempt to destroy the
object when there are no more references left. As an example, the factory function:
shared_ptr<X> createX();
in certain situations may need to return a pointer to a statically allocated `X` instance.
The solution is to use a custom deleter that does nothing:
```
struct null_deleter
{
void operator()(void const *) const
{
}
};
static X x;
shared_ptr<X> createX()
{
shared_ptr<X> px(&x, null_deleter());
return px;
}
```
The same technique works for any object known to outlive the pointer.
## Using a shared_ptr to hold a pointer to a COM Object
Background: COM objects have an embedded reference count and two member functions that manipulate it. `AddRef()` increments the count.
`Release()` decrements the count and destroys itself when the count drops to zero.
It is possible to hold a pointer to a COM object in a `shared_ptr`:
shared_ptr<IWhatever> make_shared_from_COM(IWhatever * p)
{
p->AddRef();
shared_ptr<IWhatever> pw(p, mem_fn(&IWhatever::Release));
return pw;
}
Note, however, that `shared_ptr` copies created from `pw` will not "register" in the embedded count of the COM object;
they will share the single reference created in `make_shared_from_COM`. Weak pointers created from `pw` will be invalidated when the last
`shared_ptr` is destroyed, regardless of whether the COM object itself is still alive.
As link:../../../../libs/bind/mem_fn.html#Q3[explained] in the `mem_fn` documentation, you need to `#define BOOST_MEM_FN_ENABLE_STDCALL` first.
[#techniques_intrusive]
## Using a shared_ptr to hold a pointer to an object with an embedded reference count
This is a generalization of the above technique. The example assumes that the object implements the two functions required by `<<intrusive_ptr,intrusive_ptr>>`,
`intrusive_ptr_add_ref` and `intrusive_ptr_release`:
```
template<class T> struct intrusive_deleter
{
void operator()(T * p)
{
if(p) intrusive_ptr_release(p);
}
};
shared_ptr<X> make_shared_from_intrusive(X * p)
{
if(p) intrusive_ptr_add_ref(p);
shared_ptr<X> px(p, intrusive_deleter<X>());
return px;
}
```
## Using a shared_ptr to hold another shared ownership smart pointer
One of the design goals of `shared_ptr` is to be used in library interfaces. It is possible to encounter a situation where a library takes a
`shared_ptr` argument, but the object at hand is being managed by a different reference counted or linked smart pointer.
It is possible to exploit `shared_ptr`&#8217;s custom deleter feature to wrap this existing smart pointer behind a `shared_ptr` facade:
```
template<class P> struct smart_pointer_deleter
{
private:
P p_;
public:
smart_pointer_deleter(P const & p): p_(p)
{
}
void operator()(void const *)
{
p_.reset();
}
P const & get() const
{
return p_;
}
};
shared_ptr<X> make_shared_from_another(another_ptr<X> qx)
{
shared_ptr<X> px(qx.get(), smart_pointer_deleter< another_ptr<X> >(qx));
return px;
}
```
One subtle point is that deleters are not allowed to throw exceptions, and the above example as written assumes that `p_.reset()` doesn't throw.
If this is not the case, `p_.reset();` should be wrapped in a `try {} catch(...) {}` block that ignores exceptions. In the (usually unlikely) event
when an exception is thrown and ignored, `p_` will be released when the lifetime of the deleter ends. This happens when all references, including
weak pointers, are destroyed or reset.
Another twist is that it is possible, given the above `shared_ptr` instance, to recover the original smart pointer, using `<<shared_ptr_get_deleter,get_deleter>>`:
```
void extract_another_from_shared(shared_ptr<X> px)
{
typedef smart_pointer_deleter< another_ptr<X> > deleter;
if(deleter const * pd = get_deleter<deleter>(px))
{
another_ptr<X> qx = pd->get();
}
else
{
// not one of ours
}
}
```
[#techniques_from_raw]
## Obtaining a shared_ptr from a raw pointer
Sometimes it is necessary to obtain a `shared_ptr` given a raw pointer to an object that is already managed by another `shared_ptr` instance. Example:
void f(X * p)
{
shared_ptr<X> px(???);
}
Inside `f`, we'd like to create a `shared_ptr` to `*p`.
In the general case, this problem has no solution. One approach is to modify `f` to take a `shared_ptr`, if possible:
void f(shared_ptr<X> px);
The same transformation can be used for nonvirtual member functions, to convert the implicit `this`:
void X::f(int m);
would become a free function with a `shared_ptr` first argument:
void f(shared_ptr<X> this_, int m);
If `f` cannot be changed, but `X` uses intrusive counting, use `<<techniques_intrusive,make_shared_from_intrusive>>` described above. Or, if it's known that the `shared_ptr` created in `f` will never outlive the object, use <<techniques_static,a null deleter>>.
## Obtaining a shared_ptr (weak_ptr) to this in a constructor
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`:
```
class X
{
public:
X()
{
shared_ptr<X> this_(???);
}
};
```
In the general case, the problem cannot be solved. The `X` instance being constructed can be an automatic variable or a static variable; it can be created on the heap:
shared_ptr<X> px(new X);
but at construction time, `px` does not exist yet, and it is impossible to create another `shared_ptr` instance that shares ownership with it.
Depending on context, if the inner `shared_ptr this_` doesn't need to keep the object alive, use a `null_deleter` as explained <<techniques_static,here>> and <<techniques_weak_without_shared,here>>.
If `X` is supposed to always live on the heap, and be managed by a `shared_ptr`, use a static factory function:
```
class X
{
private:
X() { ... }
public:
static shared_ptr<X> create()
{
shared_ptr<X> px(new X);
// use px as 'this_'
return px;
}
};
```
## Obtaining a shared_ptr to this
Sometimes it is needed to obtain a `shared_ptr` from `this` in a virtual member function under the assumption that `this` is already managed by a `shared_ptr`.
The transformations <<techniques_from_raw,described in the previous technique>> cannot be applied.
A typical example:
```
class X
{
public:
virtual void f() = 0;
protected:
~X() {}
};
class Y
{
public:
virtual shared_ptr<X> getX() = 0;
protected:
~Y() {}
};
// --
class impl: public X, public Y
{
public:
impl() { ... }
virtual void f() { ... }
virtual shared_ptr<X> getX()
{
shared_ptr<X> px(???);
return px;
}
};
```
The solution is to keep a weak pointer to `this` as a member in `impl`:
```
class impl: public X, public Y
{
private:
weak_ptr<impl> weak_this;
impl(impl const &);
impl & operator=(impl const &);
impl() { ... }
public:
static shared_ptr<impl> create()
{
shared_ptr<impl> pi(new impl);
pi->weak_this = pi;
return pi;
}
virtual void f() { ... }
virtual shared_ptr<X> getX()
{
shared_ptr<X> px(weak_this);
return px;
}
};
```
The library now includes a helper class template `<<enable_shared_from_this,enable_shared_from_this>>` that can be used to encapsulate the solution:
```
class impl: public X, public Y, public enable_shared_from_this<impl>
{
public:
impl(impl const &);
impl & operator=(impl const &);
public:
virtual void f() { ... }
virtual shared_ptr<X> getX()
{
return shared_from_this();
}
}
```
Note that you no longer need to manually initialize the `weak_ptr` member in `enable_shared_from_this`. Constructing a `shared_ptr` to `impl` takes care of that.
## Using shared_ptr as a smart counted handle
Some library interfaces use opaque handles, a variation of the <<techniques_incomplete,incomplete class technique>> described above. An example:
```
typedef void * HANDLE;
HANDLE CreateProcess();
void CloseHandle(HANDLE);
```
Instead of a raw pointer, it is possible to use `shared_ptr` as the handle and get reference counting and automatic resource management for free:
```
typedef shared_ptr<void> handle;
handle createProcess()
{
shared_ptr<void> pv(CreateProcess(), CloseHandle);
return pv;
}
```
## Using shared_ptr to execute code on block exit
`shared_ptr<void>` can automatically execute cleanup code when control leaves a scope.
* Executing `f(p)`, where `p` is a pointer:
+
```
shared_ptr<void> guard(p, f);
```
* Executing arbitrary code: `f(x, y)`:
+
```
shared_ptr<void> guard(static_cast<void*>(0), bind(f, x, y));
```
## Using shared_ptr<void> to hold an arbitrary object
`shared_ptr<void>` can act as a generic object pointer similar to `void*`. When a `shared_ptr<void>` instance constructed as:
shared_ptr<void> pv(new X);
is destroyed, it will correctly dispose of the `X` object by executing `~X`.
This propery can be used in much the same manner as a raw `void*` is used to temporarily strip type information from an object pointer.
A `shared_ptr<void>` can later be cast back to the correct type by using `<<shared_ptr_static_pointer_cast,static_pointer_cast>>`.
## Associating arbitrary data with heterogeneous `shared_ptr` instances
`shared_ptr` and `weak_ptr` support `operator<` comparisons required by standard associative containers such as `std::map`. This can be
used to non-intrusively associate arbitrary data with objects managed by `shared_ptr`:
```
typedef int Data;
std::map<shared_ptr<void>, Data> userData;
// or std::map<weak_ptr<void>, Data> userData; to not affect the lifetime
shared_ptr<X> px(new X);
shared_ptr<int> pi(new int(3));
userData[px] = 42;
userData[pi] = 91;
```
## Using `shared_ptr` as a `CopyConstructible` mutex lock
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 `shared_ptr` as a mutex lock:
```
class mutex
{
public:
void lock();
void unlock();
};
shared_ptr<mutex> lock(mutex & m)
{
m.lock();
return shared_ptr<mutex>(&m, mem_fn(&mutex::unlock));
}
```
Better yet, the `shared_ptr` instance acting as a lock can be encapsulated in a dedicated `shared_lock` class:
```
class shared_lock
{
private:
shared_ptr<void> pv;
public:
template<class Mutex> explicit shared_lock(Mutex & m): pv((m.lock(), &m), mem_fn(&Mutex::unlock)) {}
};
```
`shared_lock` can now be used as:
shared_lock lock(m);
Note that `shared_lock` is not templated on the mutex type, thanks to `shared_ptr<void>`&#8217;s ability to hide type information.
## Using shared_ptr to wrap member function calls
`shared_ptr` implements the ownership semantics required from the `Wrap/CallProxy` scheme described in Bjarne Stroustrup's article
"Wrapping C++ Member Function Calls" (available online at http://www.stroustrup.com/wrapper.pdf). An implementation is given below:
```
template<class T> class pointer
{
private:
T * p_;
public:
explicit pointer(T * p): p_(p)
{
}
shared_ptr<T> operator->() const
{
p_->prefix();
return shared_ptr<T>(p_, mem_fn(&T::suffix));
}
};
class X
{
private:
void prefix();
void suffix();
friend class pointer<X>;
public:
void f();
void g();
};
int main()
{
X x;
pointer<X> px(&x);
px->f();
px->g();
}
```
## Delayed deallocation
In some situations, a single `px.reset()` can trigger an expensive deallocation in a performance-critical region:
```
class X; // ~X is expensive
class Y
{
shared_ptr<X> px;
public:
void f()
{
px.reset();
}
};
```
The solution is to postpone the potential deallocation by moving `px` to a dedicated free list that can be periodically emptied when performance and response times are not an issue:
```
vector< shared_ptr<void> > free_list;
class Y
{
shared_ptr<X> px;
public:
void f()
{
free_list.push_back(px);
px.reset();
}
};
// periodically invoke free_list.clear() when convenient
```
Another variation is to move the free list logic to the construction point by using a delayed deleter:
```
struct delayed_deleter
{
template<class T> void operator()(T * p)
{
try
{
shared_ptr<void> pv(p);
free_list.push_back(pv);
}
catch(...)
{
}
}
};
```
[#techniques_weak_without_shared]
## Weak pointers to objects not managed by a shared_ptr
Make the object hold a `shared_ptr` to itself, using a `null_deleter`:
```
class X
{
private:
shared_ptr<X> 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 & rhs): this_(this, null_deleter()), i_(rhs.i_)
{
}
// do not forget to not assign this_ in the copy assignment
X & operator=(X const & rhs)
{
i_ = rhs.i_;
}
weak_ptr<X> get_weak_ptr() const { return this_; }
};
```
When the object's lifetime ends, `X::this_` will be destroyed, and all weak pointers will automatically expire.

330
doc/smart_ptr/weak_ptr.adoc Normal file
View File

@@ -0,0 +1,330 @@
////
Copyright 1999 Greg Colvin and Beman Dawes
Copyright 2002 Darin Adler
Copyright 2002-2005, 2017 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
////
[#weak_ptr]
# weak_ptr: Non-owning Observer
:toc:
:toc-title:
:idprefix: weak_ptr_
## Description
The `weak_ptr` class template stores a "weak reference" to an object that's already managed by a `shared_ptr`.
To access the object, a `weak_ptr` can be converted to a `shared_ptr` using the `shared_ptr` constructor taking
`weak_ptr`, or the `weak_ptr` member function `lock`. When the last `shared_ptr` to the object goes away and the
object is deleted, the attempt to obtain a `shared_ptr` from the `weak_ptr` instances that refer to the deleted
object will fail: the constructor will throw an exception of type `boost::bad_weak_ptr`, and `weak_ptr::lock` will
return an empty `shared_ptr`.
Every `weak_ptr` meets the `CopyConstructible` and `Assignable` requirements of the {cpp} Standard Library, and so
can be used in standard library containers. Comparison operators are supplied so that `weak_ptr` works with the standard
library's associative containers.
`weak_ptr` operations never throw exceptions.
The class template is parameterized on `T`, the type of the object pointed to.
Compared to `shared_ptr`, `weak_ptr` provides a very limited subset of operations since accessing its stored pointer is
often dangerous in multithreaded programs, and sometimes unsafe even within a single thread (that is, it may invoke undefined
behavior.) Pretend for a moment that `weak_ptr` had a get member function that returned a raw pointer, and consider this innocent
piece of code:
```
shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);
// some time later
if(int * r = q.get())
{
// use *r
}
```
Imagine that after the `if`, but immediately before `r` is used, another thread executes the statement `p.reset()`. Now `r` is a dangling pointer.
The solution to this problem is to create a temporary `shared_ptr` from `q`:
```
shared_ptr<int> p(new int(5));
weak_ptr<int> q(p);
// some time later
if(shared_ptr<int> r = q.lock())
{
// use *r
}
```
Now `r` holds a reference to the object that was pointed by `q`. Even if `p.reset()` is executed in another thread, the object will stay alive until
`r` goes out of scope or is reset. By obtaining a `shared_ptr` to the object, we have effectively locked it against destruction.
## Synopsis
`weak_ptr` is defined in `<boost/smart_ptr/weak_ptr.hpp>`.
```
namespace boost {
template<class T> class weak_ptr {
public:
typedef /*see below*/ element_type;
weak_ptr() noexcept;
template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept;
weak_ptr(weak_ptr const & r) noexcept;
template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept;
weak_ptr(weak_ptr && r) noexcept;
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;
~weak_ptr() noexcept;
weak_ptr & operator=(weak_ptr const & r) noexcept;
weak_ptr & operator=(weak_ptr && r) noexcept;
template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;
template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept;
long use_count() const noexcept;
bool expired() const noexcept;
bool empty() const noexcept;
shared_ptr<T> lock() const noexcept;
void reset() noexcept;
void swap(weak_ptr<T> & b) noexcept;
template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;
template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;
};
template<class T, class U>
bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept;
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept;
}
```
## Members
### element_type
```
typedef ... element_type;
```
`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`.
### constructors
```
weak_ptr() noexcept;
```
[none]
* {blank}
+
Effects:: Constructs an empty `weak_ptr`.
Postconditions:: `use_count() == 0`.
```
template<class Y> weak_ptr(shared_ptr<Y> const & r) noexcept;
```
```
weak_ptr(weak_ptr const & r) noexcept;
```
```
template<class Y> weak_ptr(weak_ptr<Y> const & r) noexcept;
```
[none]
* {blank}
+
Effects:: If `r` is empty, constructs an empty `weak_ptr`; otherwise, constructs a `weak_ptr` that shares ownership with `r` as if by storing a copy of the pointer stored in `r`.
Postconditions:: `use_count() == r.use_count()`.
```
weak_ptr(weak_ptr && r) noexcept;
```
[none]
* {blank}
+
Effects:: Constructs a `weak_ptr` that has the value `r` held.
Postconditions:: `r` is empty.
### aliasing constructors
```
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
```
```
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;
```
```
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;
```
Effects:: Constructs a `weak_ptr` from `r` as if by using the corresponding converting/copy/move constructor, but stores `p` instead.
Postconditions:: `use_count() == r.use_count()`. When `!expired()`, `shared_ptr<T>(*this).get() == p`.
NOTE: These constructors are an extension, not present in `std::weak_ptr`.
### destructor
```
~weak_ptr() noexcept;
```
[none]
* {blank}
+
Effects:: Destroys this `weak_ptr` but has no effect on the object its stored pointer points to.
### assignment
```
weak_ptr & operator=(weak_ptr const & r) noexcept;
```
```
weak_ptr & operator=(weak_ptr && r) noexcept;
```
```
template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r) noexcept;
```
```
template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `weak_ptr(r).swap(*this)`.
NOTE: The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary.
### use_count
```
long use_count() const noexcept;
```
[none]
* {blank}
+
Returns:: 0 if `*this` is empty; otherwise, the number of `shared_ptr` objects that share ownership with `*this`.
### expired
```
bool expired() const noexcept;
```
[none]
* {blank}
+
Returns:: `use_count() == 0`.
### empty
```
bool empty() const noexcept;
```
[none]
* {blank}
+
Returns:: `true` when `*this` is empty, `false` otherwise.
NOTE: This function is an extension, not present in `std::weak_ptr`.
### lock
```
shared_ptr<T> lock() const noexcept;
```
[none]
* {blank}
+
Returns:: `expired()? shared_ptr<T>(): shared_ptr<T>(*this)`.
### reset
```
void reset() noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `weak_ptr().swap(*this)`.
### swap
```
void swap(weak_ptr & b) noexcept;
```
[none]
* {blank}
+
Effects:: Exchanges the contents of the two smart pointers.
```
template<class Y> bool owner_before( weak_ptr<Y> const & r ) const noexcept;
```
```
template<class Y> bool owner_before( shared_ptr<Y> const & r ) const noexcept;
```
[none]
* {blank}
+
Returns:: See the description of `operator<`.
## Free Functions
### comparison
```
template<class T, class U>
bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) noexcept;
```
[none]
* {blank}
+
Returns:: An unspecified value such that
- `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard;
- under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `weak_ptr` instances
are equivalent if and only if they share ownership or are both empty.
NOTE: Allows `weak_ptr` objects to be used as keys in associative containers.
### swap
```
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) noexcept;
```
[none]
* {blank}
+
Effects:: Equivalent to `a.swap(b)`.
## Frequently Asked Questions
[qanda]
Can an object create a weak_ptr to itself in its constructor?::
No. A `weak_ptr` can only be created from a `shared_ptr`, and at object construction time no
`shared_ptr` to the object exists yet. Even if you could create a temporary `shared_ptr` to `this`,
it would go out of scope at the end of the constructor, and all `weak_ptr` instances would instantly expire.
+
The solution is to make the constructor private, and supply a factory function that returns a `shared_ptr`:
+
```
class X
{
private:
X();
public:
static shared_ptr<X> create()
{
shared_ptr<X> px(new X);
// create weak pointers from px here
return px;
}
};
```

View File

@@ -1,110 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>enable_shared_from_this</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body text="#000000" bgcolor="#ffffff" link="#0000ff" vlink="#0000ff">
<h1><img height="86" alt="boost.png (6897 bytes)" src="../../boost.png"
width="277" align="middle" border="0" />enable_shared_from_this</h1>
<h2><a name="Purpose">Purpose</a></h2>
<p>
The header <code>&lt;boost/enable_shared_from_this.hpp&gt;</code> defines
the class template <code>enable_shared_from_this</code>. It is used as a
base class that allows a <a href="shared_ptr.htm">shared_ptr</a> or
a <a href="weak_ptr.htm">weak_ptr</a> to the current object to be obtained
from within a member function.
</p>
<p><code>enable_shared_from_this&lt;T&gt;</code> defines two member functions
called <code>shared_from_this</code> that return a <code>shared_ptr&lt;T&gt;</code>
and <code>shared_ptr&lt;T const&gt;</code>, depending on constness, to <code>this</code>.
It also defines two member functions called <code>weak_from_this</code> that return
a corresponding <code>weak_ptr</code>.
</p>
<h2><a name="Example">Example</a></h2>
<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>
<h2><a name="Synopsis">Synopsis</a></h2>
<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;
weak_ptr&lt;T&gt; weak_from_this() noexcept;
weak_ptr&lt;T const&gt; weak_from_this() const noexcept;
}
}
</pre>
<h4><code>template&lt;class T&gt; shared_ptr&lt;T&gt;
enable_shared_from_this&lt;T&gt;::shared_from_this();</code></h4>
<h4><code>template&lt;class T&gt; shared_ptr&lt;T const&gt;
enable_shared_from_this&lt;T&gt;::shared_from_this() const;</code></h4>
<blockquote>
<p>
<b>Requires:</b> <code>enable_shared_from_this&lt;T&gt;</code> must be an
accessible base class of <code>T</code>. <code>*this</code> must be a subobject
of an instance <code>t</code> of type <code>T</code>.
</p>
<p>
<b>Returns:</b> If a <code>shared_ptr</code> instance <code>p</code> that <em>owns</em>
<code>t</code> exists, a <code>shared_ptr&lt;T&gt;</code> instance <code>r</code> that shares
ownership with <code>p</code>.
</p>
<p>
<b>Postconditions:</b> <code>r.get() == this</code>.
</p>
<p>
<b>Throws:</b> <code>bad_weak_ptr</code> when no <code>shared_ptr</code> <em>owns</em> <code>*this</code>.
</p>
</blockquote>
<h4><code>template&lt;class T&gt; weak_ptr&lt;T&gt;
enable_shared_from_this&lt;T&gt;::weak_from_this() noexcept;</code></h4>
<h4><code>template&lt;class T&gt; weak_ptr&lt;T const&gt;
enable_shared_from_this&lt;T&gt;::weak_from_this() const noexcept;</code></h4>
<blockquote>
<p>
<b>Requires:</b> <code>enable_shared_from_this&lt;T&gt;</code> must be an
accessible base class of <code>T</code>. <code>*this</code> must be a subobject
of an instance <code>t</code> of type <code>T</code>.
</p>
<p>
<b>Returns:</b> If a <code>shared_ptr</code> instance <code>p</code> that <em>owns</em>
<code>t</code> exists or has existed in the past, a <code>weak_ptr&lt;T&gt;</code> instance
<code>r</code> that shares ownership with <code>p</code>. Otherwise, an empty <code>weak_ptr</code>.
</p>
</blockquote>
<hr />
<p>
<small>Copyright &copy; 2002, 2003, 2015 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

@@ -62,7 +62,7 @@ int main()
clock_t t = clock();
pthread_t a[ m ];
boost::detail::lw_thread_t a[ m ];
for( int i = 0; i < m; ++i )
{
@@ -71,7 +71,7 @@ int main()
for( int j = 0; j < m; ++j )
{
pthread_join( a[j], 0 );
boost::detail::lw_thread_join( a[j] );
}
t = clock() - t;

View File

@@ -228,7 +228,7 @@ int main( int ac, char const * av[] )
clock_t t = clock();
std::vector<pthread_t> a( m );
std::vector<boost::detail::lw_thread_t> a( m );
for( int i = 0; i < m; ++i )
{
@@ -237,7 +237,7 @@ int main( int ac, char const * av[] )
for( int j = 0; j < m; ++j )
{
pthread_join( a[ j ], 0 );
boost::detail::lw_thread_join( a[ j ] );
}
t = clock() - t;

View File

@@ -165,7 +165,7 @@ int main()
clock_t t = clock();
pthread_t a[ mr+mw ];
boost::detail::lw_thread_t a[ mr+mw ];
for( int i = 0; i < mr; ++i )
{
@@ -179,7 +179,7 @@ int main()
for( int j = 0; j < mr+mw; ++j )
{
pthread_join( a[ j ], 0 );
boost::detail::lw_thread_join( a[ j ] );
}
t = clock() - t;

View File

@@ -100,7 +100,7 @@ int main()
clock_t t = clock();
pthread_t a[ m ];
boost::detail::lw_thread_t a[ m ];
for( int i = 0; i < m; ++i )
{
@@ -111,7 +111,7 @@ int main()
for( int j = 0; j < m; ++j )
{
pthread_join( a[j], 0 );
boost::detail::lw_thread_join( a[j] );
}
t = clock() - t;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

View File

@@ -10,30 +10,59 @@
// boost/detail/lightweight_thread.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2008 Peter Dimov
// Copyright (c) 2008, 2018 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
//
//
// typedef /*...*/ lw_thread_t; // as pthread_t
// template<class F> int lw_thread_create( lw_thread_t & th, F f );
// void lw_thread_join( lw_thread_t th );
#include <boost/config.hpp>
#include <memory>
#include <cerrno>
// pthread_create, pthread_join
#if defined( BOOST_HAS_PTHREADS )
#include <pthread.h>
#else
namespace boost
{
namespace detail
{
typedef ::pthread_t lw_thread_t;
inline int lw_thread_create_( lw_thread_t* thread, const pthread_attr_t* attr, void* (*start_routine)( void* ), void* arg )
{
return ::pthread_create( thread, attr, start_routine, arg );
}
inline void lw_thread_join( lw_thread_t th )
{
::pthread_join( th, 0 );
}
} // namespace detail
} // namespace boost
#else // defined( BOOST_HAS_PTHREADS )
#include <windows.h>
#include <process.h>
typedef HANDLE pthread_t;
namespace boost
{
namespace detail
{
int pthread_create( pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg )
typedef HANDLE lw_thread_t;
inline int lw_thread_create_( lw_thread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg )
{
HANDLE h = (HANDLE)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
@@ -48,20 +77,20 @@ int pthread_create( pthread_t * thread, void const *, unsigned (__stdcall * star
}
}
int pthread_join( pthread_t thread, void ** /*value_ptr*/ )
inline void lw_thread_join( lw_thread_t thread )
{
::WaitForSingleObject( thread, INFINITE );
::CloseHandle( thread );
return 0;
}
#endif
} // namespace detail
} // namespace boost
#endif // defined( BOOST_HAS_PTHREADS )
// template<class F> int lw_thread_create( pthread_t & pt, F f );
namespace boost
{
namespace detail
{
@@ -77,8 +106,16 @@ public:
extern "C" void * lw_thread_routine( void * pv )
{
#if defined(BOOST_NO_CXX11_SMART_PTR)
std::auto_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
#else
std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
#endif
pt->run();
return 0;
@@ -88,8 +125,16 @@ extern "C" void * lw_thread_routine( void * pv )
unsigned __stdcall lw_thread_routine( void * pv )
{
#if defined(BOOST_NO_CXX11_SMART_PTR)
std::auto_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
#else
std::unique_ptr<lw_abstract_thread> pt( static_cast<lw_abstract_thread *>( pv ) );
#endif
pt->run();
return 0;
@@ -115,11 +160,19 @@ private:
F f_;
};
template<class F> int lw_thread_create( pthread_t & pt, F f )
template<class F> int lw_thread_create( lw_thread_t & th, F f )
{
#if defined(BOOST_NO_CXX11_SMART_PTR)
std::auto_ptr<lw_abstract_thread> p( new lw_thread_impl<F>( f ) );
int r = pthread_create( &pt, 0, lw_thread_routine, p.get() );
#else
std::unique_ptr<lw_abstract_thread> p( new lw_thread_impl<F>( f ) );
#endif
int r = lw_thread_create_( &th, 0, lw_thread_routine, p.get() );
if( r == 0 )
{

View File

@@ -10,7 +10,7 @@
// 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
// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/smart_ptr/enable_shared_from_this.hpp>

View File

@@ -10,7 +10,7 @@
// 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.
// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/smart_ptr/intrusive_ptr.hpp>

View File

@@ -9,8 +9,7 @@
// 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.
// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/make_shared.hpp>

View File

@@ -1,10 +1,9 @@
/*
(c) 2014 Glen Joseph Fernandes
<glenjofe -at- gmail.com>
Copyright 2014 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software
License, Version 1.0.
http://boost.org/LICENSE_1_0.txt
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_MAKE_UNIQUE_HPP_INCLUDED
#define BOOST_MAKE_UNIQUE_HPP_INCLUDED

View File

@@ -10,36 +10,113 @@
#ifndef BOOST_POINTER_CAST_HPP
#define BOOST_POINTER_CAST_HPP
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
namespace boost {
//static_pointer_cast overload for raw pointers
template<class T, class U>
inline T* static_pointer_cast(U *ptr)
inline T* static_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
{
return static_cast<T*>(ptr);
}
//dynamic_pointer_cast overload for raw pointers
template<class T, class U>
inline T* dynamic_pointer_cast(U *ptr)
inline T* dynamic_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
{
return dynamic_cast<T*>(ptr);
}
//const_pointer_cast overload for raw pointers
template<class T, class U>
inline T* const_pointer_cast(U *ptr)
inline T* const_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
{
return const_cast<T*>(ptr);
}
//reinterpret_pointer_cast overload for raw pointers
template<class T, class U>
inline T* reinterpret_pointer_cast(U *ptr)
inline T* reinterpret_pointer_cast(U *ptr) BOOST_SP_NOEXCEPT
{
return reinterpret_cast<T*>(ptr);
}
} // namespace boost
#if !defined( BOOST_NO_CXX11_SMART_PTR )
#include <boost/type_traits/has_virtual_destructor.hpp>
#include <boost/static_assert.hpp>
#include <memory>
namespace boost {
//static_pointer_cast overload for std::shared_ptr
using std::static_pointer_cast;
//dynamic_pointer_cast overload for std::shared_ptr
using std::dynamic_pointer_cast;
//const_pointer_cast overload for std::shared_ptr
using std::const_pointer_cast;
//reinterpret_pointer_cast overload for std::shared_ptr
template<class T, class U> std::shared_ptr<T> reinterpret_pointer_cast(const std::shared_ptr<U> & r ) BOOST_SP_NOEXCEPT
{
(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
typedef typename std::shared_ptr<T>::element_type E;
E * p = reinterpret_cast< E* >( r.get() );
return std::shared_ptr<T>( r, p );
}
//static_pointer_cast overload for std::unique_ptr
template<class T, class U> std::unique_ptr<T> static_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) static_cast< T* >( static_cast< U* >( 0 ) );
typedef typename std::unique_ptr<T>::element_type E;
return std::unique_ptr<T>( static_cast<E*>( r.release() ) );
}
//dynamic_pointer_cast overload for std::unique_ptr
template<class T, class U> std::unique_ptr<T> dynamic_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
BOOST_STATIC_ASSERT_MSG( boost::has_virtual_destructor<T>::value, "The target of dynamic_pointer_cast must have a virtual destructor." );
T * p = dynamic_cast<T*>( r.get() );
if( p ) r.release();
return std::unique_ptr<T>( p );
}
//const_pointer_cast overload for std::unique_ptr
template<class T, class U> std::unique_ptr<T> const_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) const_cast< T* >( static_cast< U* >( 0 ) );
typedef typename std::unique_ptr<T>::element_type E;
return std::unique_ptr<T>( const_cast<E*>( r.release() ) );
}
//reinterpret_pointer_cast overload for std::unique_ptr
template<class T, class U> std::unique_ptr<T> reinterpret_pointer_cast( std::unique_ptr<U> && r ) BOOST_SP_NOEXCEPT
{
(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
typedef typename std::unique_ptr<T>::element_type E;
return std::unique_ptr<T>( reinterpret_cast<E*>( r.release() ) );
}
} // namespace boost
#endif // #if !defined( BOOST_NO_CXX11_SMART_PTR )
#endif //BOOST_POINTER_CAST_HPP

View File

@@ -12,7 +12,7 @@
// (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
// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
namespace boost

View File

@@ -8,8 +8,7 @@
// 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
//
// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/scoped_array.hpp>

View File

@@ -8,8 +8,7 @@
// 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
//
// See http://www.boost.org/libs/smart_ptr/ for documentation.
#include <boost/smart_ptr/scoped_ptr.hpp>

View File

@@ -11,7 +11,7 @@
// 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.
// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/smart_ptr/shared_array.hpp>

View File

@@ -11,7 +11,7 @@
// 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.
// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/smart_ptr/shared_ptr.hpp>

View File

@@ -11,21 +11,16 @@
// 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
// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#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>
# include <boost/make_shared.hpp>
#endif
#include <boost/weak_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/make_shared.hpp>
#endif // #ifndef BOOST_SMART_PTR_HPP_INCLUDED

View File

@@ -0,0 +1,177 @@
/*
Copyright 2017-2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
#include <boost/smart_ptr/allocate_shared_array.hpp>
#include <boost/smart_ptr/local_shared_ptr.hpp>
namespace boost {
namespace detail {
class BOOST_SYMBOL_VISIBLE lsp_array_base
: public local_counted_base {
public:
void set(sp_counted_base* base) BOOST_SP_NOEXCEPT {
count_ = shared_count(base);
}
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT {
shared_count().swap(count_);
}
virtual shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT {
return count_;
}
private:
shared_count count_;
};
template<class A>
class lsp_array_state
: public sp_array_state<A> {
public:
template<class U>
lsp_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
: sp_array_state<A>(other, size) { }
lsp_array_base& base() BOOST_SP_NOEXCEPT {
return base_;
}
private:
lsp_array_base base_;
};
template<class A, std::size_t N>
class lsp_size_array_state
: public sp_size_array_state<A, N> {
public:
template<class U>
lsp_size_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
: sp_size_array_state<A, N>(other, size) { }
lsp_array_base& base() BOOST_SP_NOEXCEPT {
return base_;
}
private:
lsp_array_base base_;
};
} /* detail */
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator, std::size_t count)
{
typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, start, count);
detail::lsp_array_base& local = node->state().base();
local.set(node);
result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
&local);
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator)
{
enum {
count = extent<T>::value
};
typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::lsp_size_array_state<other, count> state;
typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, start, count);
detail::lsp_array_base& local = node->state().base();
local.set(node);
result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
&local);
}
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator, std::size_t count,
const typename remove_extent<T>::type& value)
{
typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, start, count, value);
detail::lsp_array_base& local = node->state().base();
local.set(node);
result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
&local);
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator,
const typename remove_extent<T>::type& value)
{
enum {
count = extent<T>::value
};
typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::lsp_size_array_state<other, count> state;
typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, start, count, value);
detail::lsp_array_base& local = node->state().base();
local.set(node);
result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
&local);
}
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared_noinit(const A& allocator, std::size_t count)
{
return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator),
count);
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared_noinit(const A& allocator)
{
return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator));
}
} /* boost */
#endif

View File

@@ -1,181 +1,362 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
Copyright 2012-2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
#include <boost/smart_ptr/detail/array_count_impl.hpp>
#include <boost/smart_ptr/detail/sp_if_array.hpp>
#include <boost/core/alloc_construct.hpp>
#include <boost/core/first_scalar.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/extent.hpp>
#include <boost/type_traits/is_bounded_array.hpp>
#include <boost/type_traits/is_unbounded_array.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
namespace boost {
template<class T, class A>
inline typename boost::detail::sp_if_array<T>::type
allocate_shared(const A& allocator, std::size_t size) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
T1* p1 = 0;
T2* p2 = 0;
D1 d1;
A1 a1(allocator, size, &p2);
shared_ptr<T> s1(p1, d1, a1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(0);
namespace detail {
template<class T>
struct sp_array_element {
typedef typename boost::remove_cv<typename
boost::remove_extent<T>::type>::type type;
};
template<class T>
struct sp_array_count {
enum {
value = 1
};
};
template<class T, std::size_t N>
struct sp_array_count<T[N]> {
enum {
value = N * sp_array_count<T>::value
};
};
template<std::size_t N, std::size_t M>
struct sp_max_size {
enum {
value = N < M ? M : N
};
};
template<std::size_t N, std::size_t M>
struct sp_align_up {
enum {
value = (N + M - 1) & ~(M - 1)
};
};
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
boost::detail::as_init(allocator, p2, n1);
template<class A, class T>
struct sp_bind_allocator {
typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
};
#else
boost::detail::ms_init(p2, n1);
template<class A, class T>
struct sp_bind_allocator {
typedef typename A::template rebind<T>::other type;
};
#endif
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
return shared_ptr<T>(s1, p1);
}
template<class T, class A>
inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared(const A& allocator) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1;
enum {
N = boost::detail::array_total<T>::size
};
T1* p1 = 0;
T2* p2 = 0;
D1 d1;
A1 a1(allocator, &p2);
shared_ptr<T> s1(p1, d1, a1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(0);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
boost::detail::as_init(allocator, p2, N);
#else
boost::detail::ms_init(p2, N);
#endif
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
return shared_ptr<T>(s1, p1);
}
template<class T, class A>
inline typename boost::detail::sp_if_array<T>::type
allocate_shared(const A& allocator, std::size_t size,
const typename boost::detail::array_inner<T>::type& value) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1;
enum {
M = boost::detail::array_total<T1>::size
};
std::size_t n1 = M * size;
T1* p1 = 0;
T2* p2 = 0;
T3* p3 = reinterpret_cast<T3*>(&value);
D1 d1;
A1 a1(allocator, size, &p2);
shared_ptr<T> s1(p1, d1, a1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(0);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
boost::detail::as_init<T2, A, M>(allocator, p2, n1, p3);
#else
boost::detail::ms_init<T2, M>(p2, n1, p3);
#endif
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
return shared_ptr<T>(s1, p1);
}
template<class T, class A>
inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared(const A& allocator,
const typename boost::detail::array_inner<T>::type& value) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1;
enum {
N = boost::detail::array_total<T>::size,
M = boost::detail::array_total<T1>::size
};
T1* p1 = 0;
T2* p2 = 0;
T3* p3 = reinterpret_cast<T3*>(&value);
D1 d1;
A1 a1(allocator, &p2);
shared_ptr<T> s1(p1, d1, a1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(0);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
boost::detail::as_init<T2, A, M>(allocator, p2, N, p3);
#else
boost::detail::ms_init<T2, M>(p2, N, p3);
#endif
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
return shared_ptr<T>(s1, p1);
}
template<class T, class A>
inline typename boost::detail::sp_if_array<T>::type
allocate_shared_noinit(const A& allocator, std::size_t size) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_noinit_tag R1;
typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
T1* p1 = 0;
T2* p2 = 0;
D1 d1;
A1 a1(allocator, size, &p2);
shared_ptr<T> s1(p1, d1, a1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(0);
boost::detail::ms_noinit(p2, n1);
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
return shared_ptr<T>(s1, p1);
}
template<class T, class A>
inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared_noinit(const A& allocator) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_noinit_tag R1;
typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1;
enum {
N = boost::detail::array_total<T>::size
};
T1* p1 = 0;
T2* p2 = 0;
D1 d1;
A1 a1(allocator, &p2);
shared_ptr<T> s1(p1, d1, a1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(0);
boost::detail::ms_noinit(p2, N);
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
return shared_ptr<T>(s1, p1);
}
template<class T>
BOOST_CONSTEXPR inline std::size_t
sp_objects(std::size_t size) BOOST_SP_NOEXCEPT
{
return (size + sizeof(T) - 1) / sizeof(T);
}
template<class A>
class sp_array_state {
public:
typedef A type;
template<class U>
sp_array_state(const U& _allocator, std::size_t _size) BOOST_SP_NOEXCEPT
: allocator_(_allocator),
size_(_size) { }
A& allocator() BOOST_SP_NOEXCEPT {
return allocator_;
}
std::size_t size() const BOOST_SP_NOEXCEPT {
return size_;
}
private:
A allocator_;
std::size_t size_;
};
template<class A, std::size_t N>
class sp_size_array_state {
public:
typedef A type;
template<class U>
sp_size_array_state(const U& _allocator, std::size_t) BOOST_SP_NOEXCEPT
: allocator_(_allocator) { }
A& allocator() BOOST_SP_NOEXCEPT {
return allocator_;
}
BOOST_CONSTEXPR std::size_t size() const BOOST_SP_NOEXCEPT {
return N;
}
private:
A allocator_;
};
template<class T, class U>
struct sp_array_alignment {
enum {
value = sp_max_size<boost::alignment_of<T>::value,
boost::alignment_of<U>::value>::value
};
};
template<class T, class U>
struct sp_array_offset {
enum {
value = sp_align_up<sizeof(T), sp_array_alignment<T, U>::value>::value
};
};
template<class U, class T>
inline U*
sp_array_start(T* base) BOOST_SP_NOEXCEPT
{
enum {
size = sp_array_offset<T, U>::value
};
return reinterpret_cast<U*>(reinterpret_cast<char*>(base) + size);
}
template<class A, class T>
class sp_array_creator {
typedef typename A::value_type element;
enum {
offset = sp_array_offset<T, element>::value
};
typedef typename boost::type_with_alignment<sp_array_alignment<T,
element>::value>::type type;
public:
template<class U>
sp_array_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
: other_(other),
size_(sp_objects<type>(offset + sizeof(element) * size)) { }
T* create() {
return reinterpret_cast<T*>(other_.allocate(size_));
}
void destroy(T* base) {
other_.deallocate(reinterpret_cast<type*>(base), size_);
}
private:
typename sp_bind_allocator<A, type>::type other_;
std::size_t size_;
};
template<class T>
class BOOST_SYMBOL_VISIBLE sp_array_base
: public sp_counted_base {
typedef typename T::type allocator;
public:
typedef typename allocator::value_type type;
template<class A>
sp_array_base(const A& other, type* start, std::size_t size)
: state_(other, size) {
boost::alloc_construct_n(state_.allocator(),
boost::first_scalar(start),
state_.size() * sp_array_count<type>::value);
}
template<class A, class U>
sp_array_base(const A& other, type* start, std::size_t size, const U& list)
: state_(other, size) {
enum {
count = sp_array_count<type>::value
};
boost::alloc_construct_n(state_.allocator(),
boost::first_scalar(start), state_.size() * count,
boost::first_scalar(&list), count);
}
T& state() BOOST_SP_NOEXCEPT {
return state_;
}
virtual void dispose() BOOST_SP_NOEXCEPT {
boost::alloc_destroy_n(state_.allocator(),
boost::first_scalar(sp_array_start<type>(this)),
state_.size() * sp_array_count<type>::value);
}
virtual void destroy() BOOST_SP_NOEXCEPT {
sp_array_creator<allocator, sp_array_base> other(state_.allocator(),
state_.size());
this->~sp_array_base();
other.destroy(this);
}
virtual void* get_deleter(const sp_typeinfo_&) BOOST_SP_NOEXCEPT {
return 0;
}
virtual void* get_local_deleter(const sp_typeinfo_&) BOOST_SP_NOEXCEPT {
return 0;
}
virtual void* get_untyped_deleter() BOOST_SP_NOEXCEPT {
return 0;
}
private:
T state_;
};
template<class A, class T>
struct sp_array_result {
public:
template<class U>
sp_array_result(const U& other, std::size_t size)
: creator_(other, size),
result_(creator_.create()) { }
~sp_array_result() {
if (result_) {
creator_.destroy(result_);
}
}
T* get() const BOOST_SP_NOEXCEPT {
return result_;
}
void release() BOOST_SP_NOEXCEPT {
result_ = 0;
}
private:
sp_array_result(const sp_array_result&);
sp_array_result& operator=(const sp_array_result&);
sp_array_creator<A, T> creator_;
T* result_;
};
} /* detail */
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, std::size_t count)
{
typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::sp_array_state<other> state;
typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, start, count);
result.release();
return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator)
{
enum {
count = extent<T>::value
};
typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::sp_size_array_state<other, extent<T>::value> state;
typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, start, count);
result.release();
return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
}
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, std::size_t count,
const typename remove_extent<T>::type& value)
{
typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::sp_array_state<other> state;
typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, start, count, value);
result.release();
return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator,
const typename remove_extent<T>::type& value)
{
enum {
count = extent<T>::value
};
typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::sp_size_array_state<other, extent<T>::value> state;
typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get();
element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, start, count, value);
result.release();
return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
}
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared_noinit(const A& allocator, std::size_t count)
{
return boost::allocate_shared<T>(boost::noinit_adapt(allocator), count);
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared_noinit(const A& allocator)
{
return boost::allocate_shared<T>(boost::noinit_adapt(allocator));
}
} /* boost */
#endif

View File

@@ -0,0 +1,505 @@
/*
Copyright 2019 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP
#define BOOST_SMART_PTR_ALLOCATE_UNIQUE_HPP
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
#include <boost/core/alloc_construct.hpp>
#include <boost/core/empty_value.hpp>
#include <boost/core/first_scalar.hpp>
#include <boost/core/noinit_adaptor.hpp>
#include <boost/core/pointer_traits.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/extent.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_bounded_array.hpp>
#include <boost/type_traits/is_unbounded_array.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/type_identity.hpp>
#include <boost/config.hpp>
#include <memory>
#include <utility>
namespace boost {
namespace detail {
template<class T>
struct sp_alloc_size {
BOOST_STATIC_CONSTEXPR std::size_t value = 1;
};
template<class T>
struct sp_alloc_size<T[]> {
BOOST_STATIC_CONSTEXPR std::size_t value = sp_alloc_size<T>::value;
};
template<class T, std::size_t N>
struct sp_alloc_size<T[N]> {
BOOST_STATIC_CONSTEXPR std::size_t value = N * sp_alloc_size<T>::value;
};
template<class T>
struct sp_alloc_result {
typedef T type;
};
template<class T, std::size_t N>
struct sp_alloc_result<T[N]> {
typedef T type[];
};
template<class T>
struct sp_alloc_value {
typedef typename boost::remove_cv<typename
boost::remove_extent<T>::type>::type type;
};
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<class A, class T>
struct sp_alloc_to {
typedef typename std::allocator_traits<A>::template rebind_alloc<T> type;
};
#else
template<class A, class T>
struct sp_alloc_to {
typedef typename A::template rebind<T>::other type;
};
#endif
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<class A>
struct sp_alloc_type {
typedef typename std::allocator_traits<A>::pointer type;
};
#else
template<class A>
struct sp_alloc_type {
typedef typename A::pointer type;
};
#endif
template<class T, class P>
class sp_alloc_ptr {
public:
typedef T element_type;
sp_alloc_ptr() BOOST_SP_NOEXCEPT
: p_() { }
#if defined(BOOST_MSVC) && BOOST_MSVC == 1600
sp_alloc_ptr(T* p) BOOST_SP_NOEXCEPT
: p_(const_cast<typename boost::remove_cv<T>::type*>(p)) { }
#endif
sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT
: p_(p) { }
#if !defined(BOOST_NO_CXX11_NULLPTR)
sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
: p_() { }
#endif
T& operator*() const {
return *p_;
}
T* operator->() const BOOST_SP_NOEXCEPT {
return boost::to_address(p_);
}
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
explicit operator bool() const BOOST_SP_NOEXCEPT {
return !!p_;
}
#endif
bool operator!() const BOOST_SP_NOEXCEPT {
return !p_;
}
P ptr() const BOOST_SP_NOEXCEPT {
return p_;
}
BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {
return 1;
}
#if defined(BOOST_MSVC) && BOOST_MSVC < 1910
static sp_alloc_ptr pointer_to(T& v) {
return sp_alloc_ptr(1,
std::pointer_traits<P>::pointer_to(const_cast<typename
boost::remove_cv<T>::type&>(v)));
}
#endif
private:
P p_;
};
template<class T, class P>
class sp_alloc_ptr<T[], P> {
public:
typedef T element_type;
sp_alloc_ptr() BOOST_SP_NOEXCEPT
: p_() { }
sp_alloc_ptr(std::size_t n, P p) BOOST_SP_NOEXCEPT
: p_(p)
, n_(n) { }
#if !defined(BOOST_NO_CXX11_NULLPTR)
sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
: p_() { }
#endif
T& operator[](std::size_t i) const {
return p_[i];
}
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
explicit operator bool() const BOOST_SP_NOEXCEPT {
return !!p_;
}
#endif
bool operator!() const BOOST_SP_NOEXCEPT {
return !p_;
}
P ptr() const BOOST_SP_NOEXCEPT {
return p_;
}
std::size_t size() const BOOST_SP_NOEXCEPT {
return n_;
}
#if defined(BOOST_MSVC) && BOOST_MSVC < 1910
static sp_alloc_ptr pointer_to(T& v) {
return sp_alloc_ptr(n_,
std::pointer_traits<P>::pointer_to(const_cast<typename
boost::remove_cv<T>::type&>(v)));
}
#endif
private:
P p_;
std::size_t n_;
};
template<class T, std::size_t N, class P>
class sp_alloc_ptr<T[N], P> {
public:
typedef T element_type;
sp_alloc_ptr() BOOST_SP_NOEXCEPT
: p_() { }
sp_alloc_ptr(std::size_t, P p) BOOST_SP_NOEXCEPT
: p_(p) { }
#if !defined(BOOST_NO_CXX11_NULLPTR)
sp_alloc_ptr(detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
: p_() { }
#endif
T& operator[](std::size_t i) const {
return p_[i];
}
#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
explicit operator bool() const BOOST_SP_NOEXCEPT {
return !!p_;
}
#endif
bool operator!() const BOOST_SP_NOEXCEPT {
return !p_;
}
P ptr() const BOOST_SP_NOEXCEPT {
return p_;
}
BOOST_STATIC_CONSTEXPR std::size_t size() BOOST_SP_NOEXCEPT {
return N;
}
#if defined(BOOST_MSVC) && BOOST_MSVC < 1910
static sp_alloc_ptr pointer_to(T& v) {
return sp_alloc_ptr(N,
std::pointer_traits<P>::pointer_to(const_cast<typename
boost::remove_cv<T>::type&>(v)));
}
#endif
private:
P p_;
};
template<class T, class P>
inline bool
operator==(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
{
return lhs.ptr() == rhs.ptr();
}
template<class T, class P>
inline bool
operator!=(const sp_alloc_ptr<T, P>& lhs, const sp_alloc_ptr<T, P>& rhs)
{
return !(lhs == rhs);
}
#if !defined(BOOST_NO_CXX11_NULLPTR)
template<class T, class P>
inline bool
operator==(const sp_alloc_ptr<T, P>& lhs,
detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
{
return !lhs.ptr();
}
template<class T, class P>
inline bool
operator==(detail::sp_nullptr_t,
const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
{
return !rhs.ptr();
}
template<class T, class P>
inline bool
operator!=(const sp_alloc_ptr<T, P>& lhs,
detail::sp_nullptr_t) BOOST_SP_NOEXCEPT
{
return !!lhs.ptr();
}
template<class T, class P>
inline bool
operator!=(detail::sp_nullptr_t,
const sp_alloc_ptr<T, P>& rhs) BOOST_SP_NOEXCEPT
{
return !!rhs.ptr();
}
#endif
template<class A>
inline void
sp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t,
boost::false_type)
{
boost::alloc_destroy(a, boost::to_address(p));
}
template<class A>
inline void
sp_alloc_clear(A& a, typename sp_alloc_type<A>::type p, std::size_t n,
boost::true_type)
{
#if defined(BOOST_MSVC) && BOOST_MSVC < 1800
if (!p) {
return;
}
#endif
boost::alloc_destroy_n(a, boost::first_scalar(boost::to_address(p)),
n * sp_alloc_size<typename A::value_type>::value);
}
} /* detail */
template<class T, class A>
class alloc_deleter
: empty_value<typename detail::sp_alloc_to<A,
typename detail::sp_alloc_value<T>::type>::type> {
typedef typename detail::sp_alloc_to<A,
typename detail::sp_alloc_value<T>::type>::type allocator;
typedef empty_value<allocator> base;
public:
typedef detail::sp_alloc_ptr<T,
typename detail::sp_alloc_type<allocator>::type> pointer;
explicit alloc_deleter(const allocator& a) BOOST_SP_NOEXCEPT
: base(empty_init_t(), a) { }
void operator()(pointer p) {
detail::sp_alloc_clear(base::get(), p.ptr(), p.size(), is_array<T>());
base::get().deallocate(p.ptr(), p.size());
}
};
#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template<class T, class A>
using alloc_noinit_deleter = alloc_deleter<T, noinit_adaptor<A> >;
#endif
namespace detail {
template<class T, class A>
class sp_alloc_make {
public:
typedef typename sp_alloc_to<A,
typename sp_alloc_value<T>::type>::type allocator;
private:
typedef boost::alloc_deleter<T, A> deleter;
public:
typedef std::unique_ptr<typename sp_alloc_result<T>::type, deleter> type;
sp_alloc_make(const A& a, std::size_t n)
: a_(a)
, n_(n)
, p_(a_.allocate(n)) { }
~sp_alloc_make() {
if (p_) {
a_.deallocate(p_, n_);
}
}
typename allocator::value_type* get() const BOOST_SP_NOEXCEPT {
return boost::to_address(p_);
}
allocator& state() BOOST_SP_NOEXCEPT {
return a_;
}
type release() BOOST_SP_NOEXCEPT {
pointer p = p_;
p_ = pointer();
return type(typename deleter::pointer(n_, p), deleter(a_));
}
private:
typedef typename sp_alloc_type<allocator>::type pointer;
allocator a_;
std::size_t n_;
pointer p_;
};
} /* detail */
template<class T, class A>
inline typename enable_if_<!is_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc)
{
detail::sp_alloc_make<T, A> c(alloc, 1);
boost::alloc_construct(c.state(), c.get());
return c.release();
}
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class A, class... Args>
inline typename enable_if_<!is_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc, Args&&... args)
{
detail::sp_alloc_make<T, A> c(alloc, 1);
boost::alloc_construct(c.state(), c.get(), std::forward<Args>(args)...);
return c.release();
}
#endif
template<class T, class A>
inline typename enable_if_<!is_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc, typename type_identity<T>::type&& value)
{
detail::sp_alloc_make<T, A> c(alloc, 1);
boost::alloc_construct(c.state(), c.get(), std::move(value));
return c.release();
}
template<class T, class A>
inline typename enable_if_<!is_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type
allocate_unique_noinit(const A& alloc)
{
return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
}
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc, std::size_t size)
{
detail::sp_alloc_make<T, A> c(alloc, size);
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
size * detail::sp_alloc_size<T>::value);
return c.release();
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value,
std::unique_ptr<typename detail::sp_alloc_result<T>::type,
alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc)
{
detail::sp_alloc_make<T, A> c(alloc, extent<T>::value);
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
detail::sp_alloc_size<T>::value);
return c.release();
}
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, noinit_adaptor<A> > > >::type
allocate_unique_noinit(const A& alloc, std::size_t size)
{
return boost::allocate_unique<T, noinit_adaptor<A> >(alloc, size);
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value,
std::unique_ptr<typename detail::sp_alloc_result<T>::type,
alloc_deleter<T, noinit_adaptor<A> > > >::type
allocate_unique_noinit(const A& alloc)
{
return boost::allocate_unique<T, noinit_adaptor<A> >(alloc);
}
template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value,
std::unique_ptr<T, alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc, std::size_t size,
const typename remove_extent<T>::type& value)
{
detail::sp_alloc_make<T, A> c(alloc, size);
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
size * detail::sp_alloc_size<T>::value, boost::first_scalar(&value),
detail::sp_alloc_size<typename remove_extent<T>::type>::value);
return c.release();
}
template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value,
std::unique_ptr<typename detail::sp_alloc_result<T>::type,
alloc_deleter<T, A> > >::type
allocate_unique(const A& alloc,
const typename remove_extent<T>::type& value)
{
detail::sp_alloc_make<T, A> c(alloc, extent<T>::value);
boost::alloc_construct_n(c.state(), boost::first_scalar(c.get()),
detail::sp_alloc_size<T>::value, boost::first_scalar(&value),
detail::sp_alloc_size<typename remove_extent<T>::type>::value);
return c.release();
}
} /* boost */
#endif

View File

@@ -0,0 +1,238 @@
#ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
#define BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED
//
// atomic_shared_ptr.hpp
//
// Copyright 2017 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/ for documentation.
//
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/detail/spinlock.hpp>
#include <cstring>
namespace boost
{
template<class T> class atomic_shared_ptr
{
private:
boost::shared_ptr<T> p_;
mutable boost::detail::spinlock l_;
atomic_shared_ptr(const atomic_shared_ptr&);
atomic_shared_ptr& operator=(const atomic_shared_ptr&);
private:
bool compare_exchange( shared_ptr<T>& v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT
{
l_.lock();
if( p_._internal_equiv( v ) )
{
p_.swap( w );
l_.unlock();
return true;
}
else
{
shared_ptr<T> tmp( p_ );
l_.unlock();
tmp.swap( v );
return false;
}
}
public:
#if !defined( BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX ) && !defined( BOOST_NO_CXX11_CONSTEXPR )
constexpr atomic_shared_ptr() BOOST_SP_NOEXCEPT: l_ BOOST_DETAIL_SPINLOCK_INIT
{
}
atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
: p_( std::move( p ) ), l_ BOOST_DETAIL_SPINLOCK_INIT
{
}
#else
atomic_shared_ptr() BOOST_SP_NOEXCEPT
{
boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
std::memcpy( &l_, &init, sizeof( init ) );
}
atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
: p_( std::move( p ) )
#else
: p_( p )
#endif
{
boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
std::memcpy( &l_, &init, sizeof( init ) );
}
#endif
atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{
boost::detail::spinlock::scoped_lock lock( l_ );
p_.swap( r );
return *this;
}
BOOST_CONSTEXPR bool is_lock_free() const BOOST_SP_NOEXCEPT
{
return false;
}
shared_ptr<T> load() const BOOST_SP_NOEXCEPT
{
boost::detail::spinlock::scoped_lock lock( l_ );
return p_;
}
template<class M> shared_ptr<T> load( M ) const BOOST_SP_NOEXCEPT
{
boost::detail::spinlock::scoped_lock lock( l_ );
return p_;
}
operator shared_ptr<T>() const BOOST_SP_NOEXCEPT
{
boost::detail::spinlock::scoped_lock lock( l_ );
return p_;
}
void store( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{
boost::detail::spinlock::scoped_lock lock( l_ );
p_.swap( r );
}
template<class M> void store( shared_ptr<T> r, M ) BOOST_SP_NOEXCEPT
{
boost::detail::spinlock::scoped_lock lock( l_ );
p_.swap( r );
}
shared_ptr<T> exchange( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{
{
boost::detail::spinlock::scoped_lock lock( l_ );
p_.swap( r );
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
return std::move( r );
#else
return r;
#endif
}
template<class M> shared_ptr<T> exchange( shared_ptr<T> r, M ) BOOST_SP_NOEXCEPT
{
{
boost::detail::spinlock::scoped_lock lock( l_ );
p_.swap( r );
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
return std::move( r );
#else
return r;
#endif
}
template<class M> bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, M, M ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, w );
}
template<class M> bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, M ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, w );
}
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, w );
}
template<class M> bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, M, M ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, w );
}
template<class M> bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, M ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, w );
}
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, w );
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class M> bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, M, M ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, std::move( w ) );
}
template<class M> bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, M ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, std::move( w ) );
}
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, std::move( w ) );
}
template<class M> bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, M, M ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, std::move( w ) );
}
template<class M> bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, M ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, std::move( w ) );
}
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w ) BOOST_SP_NOEXCEPT
{
return compare_exchange( v, std::move( w ) );
}
#endif
};
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED

View File

@@ -17,6 +17,7 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/config.hpp>
#include <exception>
#ifdef __BORLANDC__
@@ -36,16 +37,26 @@ namespace boost
# pragma option push -pc
#endif
#if defined(BOOST_CLANG)
// Intel C++ on Mac defines __clang__ but doesn't support the pragma
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wweak-vtables"
#endif
class bad_weak_ptr: public std::exception
{
public:
virtual char const * what() const throw()
virtual char const * what() const BOOST_NOEXCEPT_OR_NOTHROW
{
return "tr1::bad_weak_ptr";
}
};
#if defined(BOOST_CLANG)
# pragma clang diagnostic pop
#endif
#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
# pragma option pop
#endif

View File

@@ -1,318 +0,0 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
#define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
#include <boost/align/align.hpp>
#include <boost/smart_ptr/detail/array_traits.hpp>
#include <boost/smart_ptr/detail/array_utility.hpp>
#include <boost/type_traits/alignment_of.hpp>
namespace boost {
namespace detail {
struct ms_init_tag { };
struct ms_noinit_tag { };
template<class T>
struct ms_allocator_state;
template<class T>
struct ms_allocator_state<T[]> {
typedef typename array_base<T>::type type;
ms_allocator_state(std::size_t size_,
type** result_)
: size(size_ * array_total<T>::size),
result(result_) {
}
std::size_t size;
union {
type** result;
type* object;
};
};
template<class T, std::size_t N>
struct ms_allocator_state<T[N]> {
typedef typename array_base<T>::type type;
ms_allocator_state(type** result_)
: result(result_) {
}
enum {
size = array_total<T[N]>::size
};
union {
type** result;
type* object;
};
};
template<class A, class T, class R>
class as_allocator
: public A {
template<class A_, class T_, class R_>
friend class as_allocator;
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef std::allocator_traits<A> AT;
typedef typename AT::template rebind_alloc<char> CA;
typedef typename AT::template rebind_traits<char> CT;
#else
typedef typename A::template rebind<char>::other CA;
#endif
public:
typedef A allocator_type;
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename AT::value_type value_type;
typedef typename AT::pointer pointer;
typedef typename AT::const_pointer const_pointer;
typedef typename AT::void_pointer void_pointer;
typedef typename AT::const_void_pointer const_void_pointer;
typedef typename AT::size_type size_type;
typedef typename AT::difference_type difference_type;
#else
typedef typename A::value_type value_type;
typedef typename A::pointer pointer;
typedef typename A::const_pointer const_pointer;
typedef typename A::size_type size_type;
typedef typename A::difference_type difference_type;
typedef typename A::reference reference;
typedef typename A::const_reference const_reference;
typedef void* void_pointer;
typedef const void* const_void_pointer;
#endif
template<class U>
struct rebind {
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef as_allocator<typename AT::
template rebind_alloc<U>, T, R> other;
#else
typedef as_allocator<typename A::
template rebind<U>::other, T, R> other;
#endif
};
typedef typename array_base<T>::type type;
as_allocator(const A& allocator_, type** result)
: A(allocator_),
data(result) {
}
as_allocator(const A& allocator_, std::size_t size,
type** result)
: A(allocator_),
data(size, result) {
}
template<class U>
as_allocator(const as_allocator<U, T, R>& other)
: A(other.allocator()),
data(other.data) {
}
pointer allocate(size_type count, const_void_pointer = 0) {
enum {
M = boost::alignment_of<type>::value
};
std::size_t n1 = count * sizeof(value_type);
std::size_t n2 = data.size * sizeof(type);
std::size_t n3 = n2 + M;
CA ca(allocator());
void* p1 = ca.allocate(n1 + n3);
void* p2 = static_cast<char*>(p1) + n1;
(void)boost::alignment::align(M, n2, p2, n3);
*data.result = static_cast<type*>(p2);
return static_cast<value_type*>(p1);
}
void deallocate(pointer memory, size_type count) {
enum {
M = boost::alignment_of<type>::value
};
std::size_t n1 = count * sizeof(value_type);
std::size_t n2 = data.size * sizeof(type) + M;
char* p1 = reinterpret_cast<char*>(memory);
CA ca(allocator());
ca.deallocate(p1, n1 + n2);
}
const A& allocator() const {
return static_cast<const A&>(*this);
}
A& allocator() {
return static_cast<A&>(*this);
}
void set(type* memory) {
data.object = memory;
}
void operator()() {
if (data.object) {
R tag;
release(tag);
}
}
private:
void release(ms_init_tag) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
as_destroy(allocator(), data.object, data.size);
#else
ms_destroy(data.object, data.size);
#endif
}
void release(ms_noinit_tag) {
ms_destroy(data.object, data.size);
}
ms_allocator_state<T> data;
};
template<class A1, class A2, class T, class R>
bool operator==(const as_allocator<A1, T, R>& a1,
const as_allocator<A2, T, R>& a2) {
return a1.allocator() == a2.allocator();
}
template<class A1, class A2, class T, class R>
bool operator!=(const as_allocator<A1, T, R>& a1,
const as_allocator<A2, T, R>& a2) {
return a1.allocator() != a2.allocator();
}
template<class T, class Y = char>
class ms_allocator;
template<class T, class Y>
class ms_allocator {
template<class T_, class Y_>
friend class ms_allocator;
public:
typedef typename array_base<T>::type type;
typedef Y value_type;
typedef Y* pointer;
typedef const Y* const_pointer;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef Y& reference;
typedef const Y& const_reference;
template<class U>
struct rebind {
typedef ms_allocator<T, U> other;
};
ms_allocator(type** result)
: data(result) {
}
ms_allocator(std::size_t size, type** result)
: data(size, result) {
}
template<class U>
ms_allocator(const ms_allocator<T, U>& other)
: data(other.data) {
}
pointer allocate(size_type count, const void* = 0) {
enum {
M = boost::alignment_of<type>::value
};
std::size_t n1 = count * sizeof(Y);
std::size_t n2 = data.size * sizeof(type);
std::size_t n3 = n2 + M;
void* p1 = ::operator new(n1 + n3);
void* p2 = static_cast<char*>(p1) + n1;
(void)boost::alignment::align(M, n2, p2, n3);
*data.result = static_cast<type*>(p2);
return static_cast<Y*>(p1);
}
void deallocate(pointer memory, size_type) {
void* p1 = memory;
::operator delete(p1);
}
#if defined(BOOST_NO_CXX11_ALLOCATOR)
pointer address(reference value) const {
return &value;
}
const_pointer address(const_reference value) const {
return &value;
}
size_type max_size() const {
enum {
N = static_cast<std::size_t>(-1) / sizeof(Y)
};
return N;
}
void construct(pointer memory, const_reference value) {
void* p1 = memory;
::new(p1) Y(value);
}
void destroy(pointer memory) {
(void)memory;
memory->~Y();
}
#endif
void set(type* memory) {
data.object = memory;
}
void operator()() {
if (data.object) {
ms_destroy(data.object, data.size);
}
}
private:
ms_allocator_state<T> data;
};
template<class T, class Y1, class Y2>
bool operator==(const ms_allocator<T, Y1>&,
const ms_allocator<T, Y2>&) {
return true;
}
template<class T, class Y1, class Y2>
bool operator!=(const ms_allocator<T, Y1>&,
const ms_allocator<T, Y2>&) {
return false;
}
class ms_in_allocator_tag {
public:
void operator()(const void*) {
}
};
}
}
#endif

View File

@@ -1,67 +0,0 @@
/*
* Copyright (c) 2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_COUNT_IMPL_HPP
#define BOOST_SMART_PTR_DETAIL_ARRAY_COUNT_IMPL_HPP
#include <boost/smart_ptr/detail/array_allocator.hpp>
#include <boost/smart_ptr/detail/sp_counted_impl.hpp>
namespace boost {
namespace detail {
template<class P, class A>
class sp_counted_impl_pda<P, ms_in_allocator_tag, A>
: public sp_counted_base {
typedef ms_in_allocator_tag D;
typedef sp_counted_impl_pda<P, D, A> Y;
public:
sp_counted_impl_pda(P, D, const A& allocator_)
: allocator(allocator_) {
}
virtual void dispose() {
allocator();
}
virtual void destroy() {
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename std::allocator_traits<A>::
template rebind_alloc<Y> YA;
typedef typename std::allocator_traits<A>::
template rebind_traits<Y> YT;
#else
typedef typename A::template rebind<Y>::other YA;
#endif
YA a1(allocator);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::destroy(a1, this);
YT::deallocate(a1, this, 1);
#else
this->~Y();
a1.deallocate(this, 1);
#endif
}
virtual void* get_deleter(const sp_typeinfo&) {
return &reinterpret_cast<char&>(allocator);
}
virtual void* get_untyped_deleter() {
return &reinterpret_cast<char&>(allocator);
}
private:
sp_counted_impl_pda(const sp_counted_impl_pda&);
sp_counted_impl_pda& operator=(const sp_counted_impl_pda&);
A allocator;
};
}
}
#endif

View File

@@ -1,60 +0,0 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP
#define BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP
#include <boost/type_traits/remove_cv.hpp>
namespace boost {
namespace detail {
template<class T>
struct array_base {
typedef typename boost::remove_cv<T>::type type;
};
template<class T>
struct array_base<T[]> {
typedef typename array_base<T>::type type;
};
template<class T, std::size_t N>
struct array_base<T[N]> {
typedef typename array_base<T>::type type;
};
template<class T>
struct array_total {
enum {
size = 1
};
};
template<class T, std::size_t N>
struct array_total<T[N]> {
enum {
size = N * array_total<T>::size
};
};
template<class T>
struct array_inner;
template<class T>
struct array_inner<T[]> {
typedef T type;
};
template<class T, std::size_t N>
struct array_inner<T[N]> {
typedef T type;
};
}
}
#endif

View File

@@ -1,214 +0,0 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP
#define BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP
#include <boost/config.hpp>
#include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp>
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
#include <memory>
#endif
namespace boost {
namespace detail {
typedef boost::true_type ms_is_trivial;
typedef boost::false_type ms_no_trivial;
template<class T>
inline void ms_destroy(T*, std::size_t, ms_is_trivial) {
}
template<class T>
inline void ms_destroy(T* memory, std::size_t size, ms_no_trivial) {
for (std::size_t i = size; i > 0;) {
memory[--i].~T();
}
}
template<class T>
inline void ms_destroy(T* memory, std::size_t size) {
boost::has_trivial_destructor<T> trivial;
ms_destroy(memory, size, trivial);
}
template<class T>
inline void ms_init(T* memory, std::size_t size, ms_is_trivial) {
for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i;
::new(p1) T();
}
}
template<class T>
inline void ms_init(T* memory, std::size_t size, ms_no_trivial) {
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
try {
for (; i < size; i++) {
void* p1 = memory + i;
::new(p1) T();
}
} catch (...) {
ms_destroy(memory, i);
throw;
}
#else
for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i;
::new(p1) T();
}
#endif
}
template<class T>
inline void ms_init(T* memory, std::size_t size) {
boost::has_trivial_default_constructor<T> trivial;
ms_init(memory, size, trivial);
}
template<class T, std::size_t N>
inline void ms_init(T* memory, std::size_t size, const T* list) {
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
try {
for (; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i % N]);
}
} catch (...) {
ms_destroy(memory, i);
throw;
}
#else
for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i % N]);
}
#endif
}
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<class T, class A>
inline void as_destroy(const A& allocator, T* memory,
std::size_t size) {
typedef typename std::allocator_traits<A>::
template rebind_alloc<T> TA;
typedef typename std::allocator_traits<A>::
template rebind_traits<T> TT;
TA a2(allocator);
for (std::size_t i = size; i > 0;) {
TT::destroy(a2, &memory[--i]);
}
}
template<class T, class A>
inline void as_init(const A& allocator, T* memory, std::size_t size,
ms_is_trivial) {
typedef typename std::allocator_traits<A>::
template rebind_alloc<T> TA;
typedef typename std::allocator_traits<A>::
template rebind_traits<T> TT;
TA a2(allocator);
for (std::size_t i = 0; i < size; i++) {
TT::construct(a2, memory + i);
}
}
template<class T, class A>
inline void as_init(const A& allocator, T* memory, std::size_t size,
ms_no_trivial) {
typedef typename std::allocator_traits<A>::
template rebind_alloc<T> TA;
typedef typename std::allocator_traits<A>::
template rebind_traits<T> TT;
TA a2(allocator);
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
try {
for (; i < size; i++) {
TT::construct(a2, memory + i);
}
} catch (...) {
as_destroy(a2, memory, i);
throw;
}
#else
for (std::size_t i = 0; i < size; i++) {
TT::construct(a2, memory + i);
}
#endif
}
template<class T, class A>
inline void as_init(const A& allocator, T* memory, std::size_t size) {
boost::has_trivial_default_constructor<T> trivial;
as_init(allocator, memory, size, trivial);
}
template<class T, class A, std::size_t N>
inline void as_init(const A& allocator, T* memory, std::size_t size,
const T* list) {
typedef typename std::allocator_traits<A>::
template rebind_alloc<T> TA;
typedef typename std::allocator_traits<A>::
template rebind_traits<T> TT;
TA a2(allocator);
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
try {
for (; i < size; i++) {
TT::construct(a2, memory + i, list[i % N]);
}
} catch (...) {
as_destroy(a2, memory, i);
throw;
}
#else
for (std::size_t i = 0; i < size; i++) {
TT::construct(a2, memory + i, list[i % N]);
}
#endif
}
#endif
template<class T>
inline void ms_noinit(T*, std::size_t, ms_is_trivial) {
}
template<class T>
inline void ms_noinit(T* memory, std::size_t size, ms_no_trivial) {
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
try {
for (; i < size; i++) {
void* p1 = memory + i;
::new(p1) T;
}
} catch (...) {
ms_destroy(memory, i);
throw;
}
#else
for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i;
::new(p1) T;
}
#endif
}
template<class T>
inline void ms_noinit(T* memory, std::size_t size) {
boost::has_trivial_default_constructor<T> trivial;
ms_noinit(memory, size, trivial);
}
}
}
#endif

View File

@@ -73,6 +73,9 @@
#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 )
# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC )
# include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp>
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined( __PATHSCALE__ )
# include <boost/smart_ptr/detail/atomic_count_gcc_x86.hpp>

View File

@@ -9,7 +9,7 @@
// 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<EFBFBD>nnes <larsbj@lyx.org>
// Copyright (c) 2002 Lars Gullik Bjønnes <larsbj@lyx.org>
// Copyright 2003-2005 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See

View File

@@ -26,7 +26,7 @@ class atomic_count
{
public:
explicit atomic_count( long v ): value_( v )
explicit atomic_count( long v ): value_( static_cast< std::int_least32_t >( v ) )
{
}

View File

@@ -28,15 +28,12 @@
#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__)
#if !defined(BOOST_NO_CXX11_HDR_MUTEX )
# include <boost/smart_ptr/detail/lwm_std_mutex.hpp>
#elif 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
# include <boost/smart_ptr/detail/lwm_pthreads.hpp>
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LIGHTWEIGHT_MUTEX_HPP_INCLUDED

View File

@@ -0,0 +1,148 @@
#ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// detail/local_counted_base.hpp
//
// Copyright 2017 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/ for documentation.
#include <boost/smart_ptr/detail/shared_count.hpp>
#include <boost/config.hpp>
#include <utility>
namespace boost
{
namespace detail
{
class BOOST_SYMBOL_VISIBLE local_counted_base
{
private:
local_counted_base & operator= ( local_counted_base const & );
private:
// not 'int' or 'unsigned' to avoid aliasing and enable optimizations
enum count_type { min_ = 0, initial_ = 1, max_ = 2147483647 };
count_type local_use_count_;
public:
BOOST_CONSTEXPR local_counted_base() BOOST_SP_NOEXCEPT: local_use_count_( initial_ )
{
}
BOOST_CONSTEXPR local_counted_base( local_counted_base const & ) BOOST_SP_NOEXCEPT: local_use_count_( initial_ )
{
}
virtual ~local_counted_base() /*BOOST_SP_NOEXCEPT*/
{
}
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT = 0;
virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT = 0;
void add_ref() BOOST_SP_NOEXCEPT
{
#if !defined(__NVCC__)
#if defined( __has_builtin )
# if __has_builtin( __builtin_assume )
__builtin_assume( local_use_count_ >= 1 );
# endif
#endif
#endif
local_use_count_ = static_cast<count_type>( local_use_count_ + 1 );
}
void release() BOOST_SP_NOEXCEPT
{
local_use_count_ = static_cast<count_type>( local_use_count_ - 1 );
if( local_use_count_ == 0 )
{
local_cb_destroy();
}
}
long local_use_count() const BOOST_SP_NOEXCEPT
{
return local_use_count_;
}
};
class BOOST_SYMBOL_VISIBLE local_counted_impl: public local_counted_base
{
private:
local_counted_impl( local_counted_impl const & );
private:
shared_count pn_;
public:
explicit local_counted_impl( shared_count const& pn ) BOOST_SP_NOEXCEPT: pn_( pn )
{
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
explicit local_counted_impl( shared_count && pn ) BOOST_SP_NOEXCEPT: pn_( std::move(pn) )
{
}
#endif
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT
{
delete this;
}
virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT
{
return pn_;
}
};
class BOOST_SYMBOL_VISIBLE local_counted_impl_em: public local_counted_base
{
public:
shared_count pn_;
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT
{
shared_count().swap( pn_ );
}
virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT
{
return pn_;
}
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED

View File

@@ -0,0 +1,91 @@
#ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// detail/local_sp_deleter.hpp
//
// Copyright 2017 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/ for documentation.
#include <boost/smart_ptr/detail/local_counted_base.hpp>
#include <boost/config.hpp>
namespace boost
{
namespace detail
{
template<class D> class local_sp_deleter: public local_counted_impl_em
{
private:
D d_;
public:
local_sp_deleter(): d_()
{
}
explicit local_sp_deleter( D const& d ) BOOST_SP_NOEXCEPT: d_( d )
{
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
explicit local_sp_deleter( D&& d ) BOOST_SP_NOEXCEPT: d_( std::move(d) )
{
}
#endif
D& deleter() BOOST_SP_NOEXCEPT
{
return d_;
}
template<class Y> void operator()( Y* p ) BOOST_SP_NOEXCEPT
{
d_( p );
}
#if !defined( BOOST_NO_CXX11_NULLPTR )
void operator()( boost::detail::sp_nullptr_t p ) BOOST_SP_NOEXCEPT
{
d_( p );
}
#endif
};
template<> class local_sp_deleter<void>
{
};
template<class D> D * get_local_deleter( local_sp_deleter<D> * p ) BOOST_SP_NOEXCEPT
{
return &p->deleter();
}
inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ ) BOOST_SP_NOEXCEPT
{
return 0;
}
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED

View File

@@ -1,37 +0,0 @@
#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,62 @@
#ifndef BOOST_SMART_PTR_DETAIL_LWM_STD_MUTEX_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_LWM_STD_MUTEX_HPP_INCLUDED
// Copyright 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt)
#include <boost/assert.hpp>
#include <mutex>
namespace boost
{
namespace detail
{
class lightweight_mutex
{
private:
std::mutex m_;
lightweight_mutex(lightweight_mutex const &);
lightweight_mutex & operator=(lightweight_mutex const &);
public:
lightweight_mutex()
{
}
class scoped_lock;
friend class scoped_lock;
class scoped_lock
{
private:
std::mutex & m_;
scoped_lock(scoped_lock const &);
scoped_lock & operator=(scoped_lock const &);
public:
scoped_lock( lightweight_mutex & m ): m_( m.m_ )
{
m_.lock();
}
~scoped_lock()
{
m_.unlock();
}
};
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LWM_STD_MUTEX_HPP_INCLUDED

View File

@@ -11,17 +11,20 @@
// boost/detail/lwm_win32_cs.hpp
//
// Copyright (c) 2002, 2003 Peter Dimov
// Copyright (c) Microsoft Corporation 2014
//
// 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/predef.h>
#ifdef BOOST_USE_WINDOWS_H
# include <windows.h>
#include <windows.h>
#else
struct _RTL_CRITICAL_SECTION;
#endif
namespace boost
@@ -46,19 +49,24 @@ struct critical_section
#endif
};
#if BOOST_PLAT_WINDOWS_RUNTIME
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSectionEx(critical_section *, unsigned long, unsigned long);
#else
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *);
#endif
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 *);
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *);
extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(::_RTL_CRITICAL_SECTION *);
extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *);
extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *);
#else
typedef ::_RTL_CRITICAL_SECTION rtl_critical_section;
#else // #ifndef BOOST_USE_WINDOWS_H
typedef ::CRITICAL_SECTION critical_section;
using ::InitializeCriticalSection;
using ::EnterCriticalSection;
using ::LeaveCriticalSection;
using ::DeleteCriticalSection;
typedef ::CRITICAL_SECTION rtl_critical_section;
#endif // #ifndef BOOST_USE_WINDOWS_H
class lightweight_mutex
@@ -74,16 +82,12 @@ public:
lightweight_mutex()
{
#if BOOST_PLAT_WINDOWS_RUNTIME
InitializeCriticalSectionEx(&cs_, 4000, 0);
#else
InitializeCriticalSection(&cs_);
#endif
boost::detail::InitializeCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_));
}
~lightweight_mutex()
{
DeleteCriticalSection(&cs_);
boost::detail::DeleteCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_));
}
class scoped_lock;
@@ -102,12 +106,12 @@ public:
explicit scoped_lock(lightweight_mutex & m): m_(m)
{
EnterCriticalSection(&m_.cs_);
boost::detail::EnterCriticalSection(reinterpret_cast< rtl_critical_section* >(&m_.cs_));
}
~scoped_lock()
{
LeaveCriticalSection(&m_.cs_);
boost::detail::LeaveCriticalSection(reinterpret_cast< rtl_critical_section* >(&m_.cs_));
}
};
};

View File

@@ -9,14 +9,14 @@
#if !defined( BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS ) && !defined( BOOST_NO_CXX11_NULLPTR )\
&& !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130))
explicit operator bool () const BOOST_NOEXCEPT
explicit operator bool () const BOOST_SP_NOEXCEPT
{
return px != 0;
}
#elif ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__)
operator bool () const BOOST_NOEXCEPT
operator bool () const BOOST_SP_NOEXCEPT
{
return px != 0;
}
@@ -29,7 +29,7 @@
typedef void (*unspecified_bool_type)( this_type*** );
operator unspecified_bool_type() const BOOST_NOEXCEPT
operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
{
return px == 0? 0: unspecified_bool;
}
@@ -41,7 +41,7 @@
typedef element_type * (this_type::*unspecified_bool_type)() const;
operator unspecified_bool_type() const BOOST_NOEXCEPT
operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
{
return px == 0? 0: &this_type::get;
}
@@ -50,7 +50,7 @@
typedef element_type * this_type::*unspecified_bool_type;
operator unspecified_bool_type() const BOOST_NOEXCEPT
operator unspecified_bool_type() const BOOST_SP_NOEXCEPT
{
return px == 0? 0: &this_type::px;
}
@@ -58,7 +58,7 @@
#endif
// operator! is redundant, but some compilers need it
bool operator! () const BOOST_NOEXCEPT
bool operator! () const BOOST_SP_NOEXCEPT
{
return px == 0;
}

View File

@@ -29,7 +29,8 @@
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
#include <boost/smart_ptr/detail/sp_counted_impl.hpp>
#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config/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
@@ -54,7 +55,7 @@ namespace boost
namespace movelib
{
template< class T, class D > class unique_ptr;
template< class T, class D > class unique_ptr;
} // namespace movelib
@@ -118,7 +119,14 @@ private:
public:
shared_count(): pi_(0) // nothrow
BOOST_CONSTEXPR shared_count() BOOST_SP_NOEXCEPT: pi_(0)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
{
}
BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ) BOOST_SP_NOEXCEPT: pi_( pi )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
@@ -249,18 +257,8 @@ public:
try
{
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
pi_ = pi;
std::allocator_traits<A2>::construct( a2, pi, p, d, a );
#else
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
pi_ = a2.allocate( 1 );
::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
#endif
}
catch(...)
{
@@ -276,28 +274,11 @@ public:
#else
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
pi_ = pi;
#else
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
#endif
pi_ = a2.allocate( 1 );
if( pi_ != 0 )
{
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
std::allocator_traits<A2>::construct( a2, pi, p, d, a );
#else
::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a );
#endif
}
else
{
@@ -333,18 +314,8 @@ public:
try
{
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
pi_ = pi;
std::allocator_traits<A2>::construct( a2, pi, p, a );
#else
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
pi_ = a2.allocate( 1 );
::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
#endif
}
catch(...)
{
@@ -360,28 +331,11 @@ public:
#else
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
impl_type * pi = std::allocator_traits<A2>::allocate( a2, 1 );
pi_ = pi;
#else
pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) );
#endif
pi_ = a2.allocate( 1 );
if( pi_ != 0 )
{
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
std::allocator_traits<A2>::construct( a2, pi, p, a );
#else
::new( static_cast< void* >( pi_ ) ) impl_type( p, a );
#endif
}
else
{
@@ -468,7 +422,7 @@ public:
r.release();
}
~shared_count() // nothrow
~shared_count() /*BOOST_SP_NOEXCEPT*/
{
if( pi_ != 0 ) pi_->release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
@@ -476,7 +430,7 @@ public:
#endif
}
shared_count(shared_count const & r): pi_(r.pi_) // nothrow
shared_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
@@ -486,7 +440,7 @@ public:
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
shared_count(shared_count && r): pi_(r.pi_) // nothrow
shared_count(shared_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif
@@ -497,9 +451,9 @@ public:
#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( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT; // constructs an empty *this when r.use_count() == 0
shared_count & operator= (shared_count const & r) // nothrow
shared_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
{
sp_counted_base * tmp = r.pi_;
@@ -513,44 +467,49 @@ public:
return *this;
}
void swap(shared_count & r) // nothrow
void swap(shared_count & r) BOOST_SP_NOEXCEPT
{
sp_counted_base * tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
long use_count() const // nothrow
long use_count() const BOOST_SP_NOEXCEPT
{
return pi_ != 0? pi_->use_count(): 0;
}
bool unique() const // nothrow
bool unique() const BOOST_SP_NOEXCEPT
{
return use_count() == 1;
}
bool empty() const // nothrow
bool empty() const BOOST_SP_NOEXCEPT
{
return pi_ == 0;
}
friend inline bool operator==(shared_count const & a, shared_count const & b)
friend inline bool operator==(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
{
return a.pi_ == b.pi_;
}
friend inline bool operator<(shared_count const & a, shared_count const & b)
friend inline bool operator<(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
{
return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
}
void * get_deleter( sp_typeinfo const & ti ) const
void * get_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
{
return pi_? pi_->get_deleter( ti ): 0;
}
void * get_untyped_deleter() const
void * get_local_deleter( sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
{
return pi_? pi_->get_local_deleter( ti ): 0;
}
void * get_untyped_deleter() const BOOST_SP_NOEXCEPT
{
return pi_? pi_->get_untyped_deleter(): 0;
}
@@ -571,14 +530,14 @@ private:
public:
weak_count(): pi_(0) // nothrow
BOOST_CONSTEXPR weak_count() BOOST_SP_NOEXCEPT: pi_(0)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
{
}
weak_count(shared_count const & r): pi_(r.pi_) // nothrow
weak_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
@@ -586,7 +545,7 @@ public:
if(pi_ != 0) pi_->weak_add_ref();
}
weak_count(weak_count const & r): pi_(r.pi_) // nothrow
weak_count(weak_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
@@ -598,7 +557,7 @@ public:
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
weak_count(weak_count && r): pi_(r.pi_) // nothrow
weak_count(weak_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id)
#endif
@@ -608,7 +567,7 @@ public:
#endif
~weak_count() // nothrow
~weak_count() /*BOOST_SP_NOEXCEPT*/
{
if(pi_ != 0) pi_->weak_release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
@@ -616,7 +575,7 @@ public:
#endif
}
weak_count & operator= (shared_count const & r) // nothrow
weak_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
{
sp_counted_base * tmp = r.pi_;
@@ -630,7 +589,7 @@ public:
return *this;
}
weak_count & operator= (weak_count const & r) // nothrow
weak_count & operator= (weak_count const & r) BOOST_SP_NOEXCEPT
{
sp_counted_base * tmp = r.pi_;
@@ -644,29 +603,29 @@ public:
return *this;
}
void swap(weak_count & r) // nothrow
void swap(weak_count & r) BOOST_SP_NOEXCEPT
{
sp_counted_base * tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
long use_count() const // nothrow
long use_count() const BOOST_SP_NOEXCEPT
{
return pi_ != 0? pi_->use_count(): 0;
}
bool empty() const // nothrow
bool empty() const BOOST_SP_NOEXCEPT
{
return pi_ == 0;
}
friend inline bool operator==(weak_count const & a, weak_count const & b)
friend inline bool operator==(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
{
return a.pi_ == b.pi_;
}
friend inline bool operator<(weak_count const & a, weak_count const & b)
friend inline bool operator<(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
{
return std::less<sp_counted_base *>()(a.pi_, b.pi_);
}
@@ -683,7 +642,7 @@ inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
}
}
inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ )
inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT: pi_( r.pi_ )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id)
#endif

View File

@@ -20,7 +20,7 @@
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
#if defined( __clang__ ) && defined( __has_extension )
#if !defined( __c2__ ) && defined( __clang__ ) && defined( __has_extension )
# if __has_extension( __c_atomic__ )
# define BOOST_SP_HAS_CLANG_C11_ATOMICS
# endif
@@ -44,6 +44,9 @@
#elif defined( BOOST_SP_HAS_CLANG_C11_ATOMICS )
# include <boost/smart_ptr/detail/sp_counted_base_clang.hpp>
#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC )
# include <boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp>
#elif defined( __SNC__ )
# include <boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp>
@@ -65,7 +68,7 @@
#elif defined( __GNUC__ ) && ( defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc ) ) && !defined(__PATHSCALE__) && !defined( _AIX )
# include <boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp>
#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) && !defined(__PATHSCALE__)
#elif defined( __GNUC__ ) && ( defined( __mips__ ) || defined( _mips ) ) && !defined(__PATHSCALE__) && !defined( __mips16 )
# include <boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp>
#elif defined( BOOST_SP_HAS_SYNC )

View File

@@ -15,7 +15,8 @@
// Lock-free algorithm by Alexander Terekhov
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <machine/sys/inline.h>
namespace boost
@@ -71,7 +72,7 @@ inline int atomic_conditional_increment( int * pw )
}
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -103,7 +104,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -20,7 +20,8 @@
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <builtins.h>
#include <sys/atomic_op.h>
@@ -63,7 +64,7 @@ inline int32_t atomic_conditional_increment( int32_t * pw )
}
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -95,7 +96,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -15,7 +15,9 @@
// 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/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
namespace boost
@@ -26,17 +28,17 @@ namespace detail
typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t;
inline void atomic_increment( atomic_int_least32_t * pw )
inline void atomic_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
__c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED );
}
inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw )
inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
return __c11_atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL );
}
inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw )
inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
// long r = *pw;
// if( r != 0 ) ++*pw;
@@ -58,54 +60,60 @@ inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t *
}
}
class sp_counted_base
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wweak-vtables"
#endif
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
atomic_int_least32_t use_count_; // #shared
atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
atomic_int_least32_t use_count_; // #shared
atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base()
sp_counted_base() BOOST_SP_NOEXCEPT
{
__c11_atomic_init( &use_count_, 1 );
__c11_atomic_init( &weak_count_, 1 );
}
virtual ~sp_counted_base() // nothrow
virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
virtual void destroy() BOOST_SP_NOEXCEPT // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy()
void add_ref_copy() BOOST_SP_NOEXCEPT
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
void release() BOOST_SP_NOEXCEPT
{
if( atomic_decrement( &use_count_ ) == 1 )
{
@@ -114,12 +122,12 @@ public:
}
}
void weak_add_ref() // nothrow
void weak_add_ref() BOOST_SP_NOEXCEPT
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
void weak_release() BOOST_SP_NOEXCEPT
{
if( atomic_decrement( &weak_count_ ) == 1 )
{
@@ -127,12 +135,16 @@ public:
}
}
long use_count() const // nothrow
long use_count() const BOOST_SP_NOEXCEPT
{
return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE );
}
};
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
} // namespace detail
} // namespace boost

View File

@@ -24,7 +24,8 @@
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
{
@@ -91,7 +92,7 @@ store:
return a;
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -123,7 +124,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -25,7 +25,8 @@
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
{
@@ -79,7 +80,7 @@ inline int atomic_conditional_increment( int * pw )
}
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -111,7 +112,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -16,7 +16,8 @@
// Lock-free algorithm by Alexander Terekhov
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
{
@@ -78,7 +79,7 @@ inline int atomic_conditional_increment( int * pw )
return rv;
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -110,7 +111,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -20,7 +20,8 @@
// Lock-free algorithm by Alexander Terekhov
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
{
@@ -38,7 +39,9 @@ inline void atomic_increment( int * pw )
(
"0:\n\t"
".set push\n\t"
#if !defined(__mips_isa_rev) || (__mips_isa_rev < 6)
".set mips2\n\t"
#endif
"ll %0, %1\n\t"
"addiu %0, 1\n\t"
"sc %0, %1\n\t"
@@ -59,7 +62,9 @@ inline int atomic_decrement( int * pw )
(
"0:\n\t"
".set push\n\t"
#if !defined(__mips_isa_rev) || (__mips_isa_rev < 6)
".set mips2\n\t"
#endif
"ll %1, %2\n\t"
"addiu %0, %1, -1\n\t"
"sc %0, %2\n\t"
@@ -85,7 +90,9 @@ inline int atomic_conditional_increment( int * pw )
(
"0:\n\t"
".set push\n\t"
#if !defined(__mips_isa_rev) || (__mips_isa_rev < 6)
".set mips2\n\t"
#endif
"ll %0, %2\n\t"
"beqz %0, 1f\n\t"
"addiu %1, %0, 1\n\t"
@@ -102,7 +109,7 @@ inline int atomic_conditional_increment( int * pw )
return rv;
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -134,7 +141,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -24,7 +24,8 @@
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
{
@@ -102,7 +103,7 @@ inline int atomic_conditional_increment( int * pw )
return rv;
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -134,7 +135,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -19,7 +19,8 @@
//
// Thanks to Michael van der Westhuizen
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <inttypes.h> // int32_t
namespace boost
@@ -87,7 +88,7 @@ inline int32_t atomic_conditional_increment( int32_t * pw )
}
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -119,7 +120,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -24,7 +24,8 @@
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
namespace boost
{
@@ -94,7 +95,7 @@ inline int atomic_conditional_increment( int * pw )
return rv;
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -126,7 +127,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -18,7 +18,10 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
namespace boost
{
@@ -26,54 +29,55 @@ namespace boost
namespace detail
{
class sp_counted_base
class BOOST_SYMBOL_VISIBLE 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)
boost::int_least32_t use_count_; // #shared
boost::int_least32_t weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
virtual void destroy() BOOST_SP_NOEXCEPT // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy()
void add_ref_copy() BOOST_SP_NOEXCEPT
{
++use_count_;
}
bool add_ref_lock() // true on success
bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
{
if( use_count_ == 0 ) return false;
++use_count_;
return true;
}
void release() // nothrow
void release() BOOST_SP_NOEXCEPT
{
if( --use_count_ == 0 )
{
@@ -82,12 +86,12 @@ public:
}
}
void weak_add_ref() // nothrow
void weak_add_ref() BOOST_SP_NOEXCEPT
{
++weak_count_;
}
void weak_release() // nothrow
void weak_release() BOOST_SP_NOEXCEPT
{
if( --weak_count_ == 0 )
{
@@ -95,7 +99,7 @@ public:
}
}
long use_count() const // nothrow
long use_count() const BOOST_SP_NOEXCEPT
{
return use_count_;
}

View File

@@ -18,8 +18,10 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <pthread.h>
namespace boost
@@ -28,15 +30,15 @@ namespace boost
namespace detail
{
class sp_counted_base
class BOOST_SYMBOL_VISIBLE 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)
boost::int_least32_t use_count_; // #shared
boost::int_least32_t weak_count_; // #weak + (#shared != 0)
mutable pthread_mutex_t m_;
@@ -70,7 +72,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()
@@ -91,7 +94,7 @@ public:
void release() // nothrow
{
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
long new_use_count = --use_count_;
boost::int_least32_t new_use_count = --use_count_;
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
if( new_use_count == 0 )
@@ -111,7 +114,7 @@ public:
void weak_release() // nothrow
{
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
long new_weak_count = --weak_count_;
boost::int_least32_t new_weak_count = --weak_count_;
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
if( new_weak_count == 0 )
@@ -123,7 +126,7 @@ public:
long use_count() const // nothrow
{
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
long r = use_count_;
boost::int_least32_t r = use_count_;
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
return r;

View File

@@ -19,7 +19,8 @@
//
// Thanks to Michael van der Westhuizen
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <inttypes.h> // uint32_t
namespace boost
@@ -82,7 +83,7 @@ inline uint32_t atomic_conditional_increment( uint32_t * pw )
}
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -114,7 +115,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -20,7 +20,8 @@
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <atomic.h>
namespace boost
@@ -29,7 +30,7 @@ namespace boost
namespace detail
{
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -61,7 +62,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -18,8 +18,9 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/spinlock_pool.hpp>
#include <boost/config.hpp>
namespace boost
{
@@ -51,7 +52,7 @@ inline int atomic_conditional_increment( int * pw )
return rv;
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -83,7 +84,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -15,7 +15,9 @@
// 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/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <atomic>
#include <cstdint>
@@ -25,17 +27,17 @@ namespace boost
namespace detail
{
inline void atomic_increment( std::atomic_int_least32_t * pw )
inline void atomic_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
pw->fetch_add( 1, std::memory_order_relaxed );
}
inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw )
inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
return pw->fetch_sub( 1, std::memory_order_acq_rel );
}
inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw )
inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
// long r = *pw;
// if( r != 0 ) ++*pw;
@@ -57,52 +59,53 @@ inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_
}
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
std::atomic_int_least32_t use_count_; // #shared
std::atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
std::atomic_int_least32_t use_count_; // #shared
std::atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 )
sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 )
{
}
virtual ~sp_counted_base() // nothrow
virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() = 0; // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT = 0;
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow
virtual void destroy() BOOST_SP_NOEXCEPT
{
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy()
void add_ref_copy() BOOST_SP_NOEXCEPT
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() // true on success
bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() // nothrow
void release() BOOST_SP_NOEXCEPT
{
if( atomic_decrement( &use_count_ ) == 1 )
{
@@ -111,12 +114,12 @@ public:
}
}
void weak_add_ref() // nothrow
void weak_add_ref() BOOST_SP_NOEXCEPT
{
atomic_increment( &weak_count_ );
}
void weak_release() // nothrow
void weak_release() BOOST_SP_NOEXCEPT
{
if( atomic_decrement( &weak_count_ ) == 1 )
{
@@ -124,7 +127,7 @@ public:
}
}
long use_count() const // nothrow
long use_count() const BOOST_SP_NOEXCEPT
{
return use_count_.load( std::memory_order_acquire );
}

View File

@@ -15,7 +15,8 @@
// 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/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <limits.h>
#if defined( __ia64__ ) && defined( __INTEL_COMPILER )
@@ -76,7 +77,7 @@ inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw )
}
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -108,7 +109,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -21,7 +21,8 @@
// formulation
//
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
extern "builtin" void __lwsync(void);
extern "builtin" void __isync(void);
@@ -70,7 +71,7 @@ inline int atomic_conditional_increment( int *pw )
}
}
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -103,7 +104,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -25,8 +25,9 @@
//
#include <boost/smart_ptr/detail/sp_interlocked.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config/workaround.hpp>
#include <boost/config.hpp>
namespace boost
{
@@ -34,7 +35,7 @@ namespace boost
namespace detail
{
class sp_counted_base
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
@@ -66,7 +67,8 @@ public:
delete this;
}
virtual void * get_deleter( sp_typeinfo const & ti ) = 0;
virtual void * get_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) = 0;
virtual void * get_untyped_deleter() = 0;
void add_ref_copy()

View File

@@ -26,6 +26,8 @@
#include <boost/checked_delete.hpp>
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/core/addressof.hpp>
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
#include <boost/smart_ptr/detail/quick_allocator.hpp>
@@ -50,7 +52,20 @@ void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn );
namespace detail
{
template<class X> class sp_counted_impl_p: public sp_counted_base
// get_local_deleter
template<class D> class local_sp_deleter;
template<class D> D * get_local_deleter( D * /*p*/ ) BOOST_SP_NOEXCEPT
{
return 0;
}
template<class D> D * get_local_deleter( local_sp_deleter<D> * p ) BOOST_SP_NOEXCEPT;
//
template<class X> class BOOST_SYMBOL_VISIBLE sp_counted_impl_p: public sp_counted_base
{
private:
@@ -70,7 +85,7 @@ public:
#endif
}
virtual void dispose() // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT
{
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_destructor_hook( px_, sizeof(X), this );
@@ -78,12 +93,17 @@ public:
boost::checked_delete( px_ );
}
virtual void * get_deleter( sp_typeinfo const & )
virtual void * get_deleter( sp_typeinfo_ const & ) BOOST_SP_NOEXCEPT
{
return 0;
}
virtual void * get_untyped_deleter()
virtual void * get_local_deleter( sp_typeinfo_ const & ) BOOST_SP_NOEXCEPT
{
return 0;
}
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT
{
return 0;
}
@@ -124,7 +144,7 @@ public:
# pragma option push -Vx-
#endif
template<class P, class D> class sp_counted_impl_pd: public sp_counted_base
template<class P, class D> class BOOST_SYMBOL_VISIBLE sp_counted_impl_pd: public sp_counted_base
{
private:
@@ -148,17 +168,22 @@ public:
{
}
virtual void dispose() // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT
{
del( ptr );
}
virtual void * get_deleter( sp_typeinfo const & ti )
virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT
{
return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
return ti == BOOST_SP_TYPEID_(D)? &reinterpret_cast<char&>( del ): 0;
}
virtual void * get_untyped_deleter()
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT
{
return ti == BOOST_SP_TYPEID_(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0;
}
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT
{
return &reinterpret_cast<char&>( del );
}
@@ -192,7 +217,7 @@ public:
#endif
};
template<class P, class D, class A> class sp_counted_impl_pda: public sp_counted_base
template<class P, class D, class A> class BOOST_SYMBOL_VISIBLE sp_counted_impl_pda: public sp_counted_base
{
private:
@@ -217,12 +242,12 @@ public:
{
}
virtual void dispose() // nothrow
virtual void dispose() BOOST_SP_NOEXCEPT
{
d_( p_ );
}
virtual void destroy() // nothrow
virtual void destroy() BOOST_SP_NOEXCEPT
{
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
@@ -236,25 +261,22 @@ public:
A2 a2( a_ );
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
std::allocator_traits<A2>::destroy( a2, this );
#else
this->~this_type();
#endif
a2.deallocate( this, 1 );
}
virtual void * get_deleter( sp_typeinfo const & ti )
virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT
{
return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;
return ti == BOOST_SP_TYPEID_( D )? &reinterpret_cast<char&>( d_ ): 0;
}
virtual void * get_untyped_deleter()
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT
{
return ti == BOOST_SP_TYPEID_( D )? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0;
}
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT
{
return &reinterpret_cast<char&>( d_ );
}

View File

@@ -22,15 +22,15 @@
#ifndef BOOST_SP_NO_SYNC
#if defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 )
#if !defined( __c2__ ) && defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 )
# define BOOST_SP_HAS_SYNC
#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 )
#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 ) && !defined( __COMPILER_VER__ )
# define BOOST_SP_HAS_SYNC
#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
#elif !defined( __c2__ ) && defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 )
#define BOOST_SP_HAS_SYNC

View File

@@ -1,34 +0,0 @@
/*
* Copyright (c) 2012-2014 Glen Joseph Fernandes
* glenfe at live dot com
*
* Distributed under the Boost Software License,
* Version 1.0. (See accompanying file LICENSE_1_0.txt
* or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP
#define BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP
#include <boost/smart_ptr/shared_ptr.hpp>
namespace boost {
namespace detail {
template<class T>
struct sp_if_array;
template<class T>
struct sp_if_array<T[]> {
typedef boost::shared_ptr<T[]> type;
};
template<class T>
struct sp_if_size_array;
template<class T, std::size_t N>
struct sp_if_size_array<T[N]> {
typedef boost::shared_ptr<T[N]> type;
};
}
}
#endif

View File

@@ -32,11 +32,21 @@
// MinGW-w64 provides intrin.h for both 32 and 64-bit targets.
# define BOOST_SP_HAS_INTRIN_H
#elif defined( __LP64__ )
// We have to use intrin.h on Cygwin 64
# define BOOST_SP_HAS_INTRIN_H
// Intel C++ on Windows on VC10+ stdlib
#elif defined( BOOST_INTEL_WIN ) && defined( _CPPLIB_VER ) && _CPPLIB_VER >= 520
# define BOOST_SP_HAS_INTRIN_H
// clang-cl on Windows on VC10+ stdlib
#elif defined( __clang__ ) && defined( _MSC_VER ) && defined( _CPPLIB_VER ) && _CPPLIB_VER >= 520
# define BOOST_SP_HAS_INTRIN_H
#endif
#if defined( BOOST_USE_WINDOWS_H )

View File

@@ -0,0 +1,48 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_NOEXCEPT_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_NOEXCEPT_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// detail/sp_noexcept.hpp
//
// Copyright 2016, 2017 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>
// BOOST_SP_NOEXCEPT
#if defined( BOOST_MSVC ) && BOOST_MSVC >= 1700 && BOOST_MSVC < 1900
# define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT_OR_NOTHROW
#else
# define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT
#endif
// BOOST_SP_NOEXCEPT_WITH_ASSERT
#if defined(BOOST_DISABLE_ASSERTS) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && defined(NDEBUG) )
# define BOOST_SP_NOEXCEPT_WITH_ASSERT BOOST_SP_NOEXCEPT
#elif defined(BOOST_ENABLE_ASSERT_HANDLER) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && !defined(NDEBUG) )
# define BOOST_SP_NOEXCEPT_WITH_ASSERT
#else
# define BOOST_SP_NOEXCEPT_WITH_ASSERT BOOST_SP_NOEXCEPT
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_NOEXCEPT_HPP_INCLUDED

View File

@@ -0,0 +1,58 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_TYPEINFO_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_TYPEINFO_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// smart_ptr/detail/sp_typeinfo_.hpp
//
// Copyright 2007, 2019 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 ) || defined( BOOST_NO_STD_TYPEINFO )
#include <boost/core/typeinfo.hpp>
namespace boost
{
namespace detail
{
typedef boost::core::typeinfo sp_typeinfo_;
} // namespace detail
} // namespace boost
#define BOOST_SP_TYPEID_(T) BOOST_CORE_TYPEID(T)
#else // defined( BOOST_NO_TYPEID ) || defined( BOOST_NO_STD_TYPEINFO )
#include <typeinfo>
namespace boost
{
namespace detail
{
typedef std::type_info sp_typeinfo_;
} // namespace detail
} // namespace boost
#define BOOST_SP_TYPEID_(T) typeid(T)
#endif // defined( BOOST_NO_TYPEID ) || defined( BOOST_NO_STD_TYPEINFO )
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_TYPEINFO_HPP_INCLUDED

View File

@@ -43,6 +43,9 @@
#elif defined( BOOST_SP_USE_PTHREADS )
# include <boost/smart_ptr/detail/spinlock_pt.hpp>
#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC )
# include <boost/smart_ptr/detail/spinlock_std_atomic.hpp>
#elif defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ )
# include <boost/smart_ptr/detail/spinlock_gcc_arm.hpp>

View File

@@ -16,6 +16,7 @@
//
#include <boost/smart_ptr/detail/yield_k.hpp>
#include <boost/config.hpp>
#include <atomic>
namespace boost
@@ -32,12 +33,12 @@ public:
public:
bool try_lock()
bool try_lock() BOOST_NOEXCEPT
{
return !v_.test_and_set( std::memory_order_acquire );
}
void lock()
void lock() BOOST_NOEXCEPT
{
for( unsigned k = 0; !try_lock(); ++k )
{
@@ -45,7 +46,7 @@ public:
}
}
void unlock()
void unlock() BOOST_NOEXCEPT
{
v_ .clear( std::memory_order_release );
}
@@ -63,12 +64,12 @@ public:
public:
explicit scoped_lock( spinlock & sp ): sp_( sp )
explicit scoped_lock( spinlock & sp ) BOOST_NOEXCEPT: sp_( sp )
{
sp.lock();
}
~scoped_lock()
~scoped_lock() /*BOOST_NOEXCEPT*/
{
sp_.unlock();
}

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