mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-10-04 19:51:02 +02:00
Compare commits
298 Commits
boost-1.62
...
boost-1.69
Author | SHA1 | Date | |
---|---|---|---|
|
04f0847af4 | ||
|
29a08cdff6 | ||
|
6d3af760f6 | ||
|
a9f39d2b94 | ||
|
4e2f236116 | ||
|
4eb53db537 | ||
|
a2b6ba85f3 | ||
|
e37cd4154f | ||
|
8563fc5c4e | ||
|
67fab5c9ec | ||
|
f16fbdce26 | ||
|
c3b3835a58 | ||
|
d1600b8abc | ||
|
5885763287 | ||
|
9bb12692b3 | ||
|
773ef80f5d | ||
|
704de2bd67 | ||
|
1caa233faa | ||
|
605d4a2789 | ||
|
6ab9b93088 | ||
|
4129bb6a5c | ||
|
3b64e5ecb3 | ||
|
4025698fe8 | ||
|
2d7ab197a7 | ||
|
5877b08490 | ||
|
ffe5b46f75 | ||
|
4abc74fe28 | ||
|
12a646c607 | ||
|
937a3e0e93 | ||
|
258fa75a7e | ||
|
93d0d69f5e | ||
|
f173f9c0fb | ||
|
6a5942f55f | ||
|
293a4ee009 | ||
|
8e3aa3a565 | ||
|
78bebd5166 | ||
|
a47cf35b0f | ||
|
8d0afb670f | ||
|
77a35856c6 | ||
|
693109361e | ||
|
6735806863 | ||
|
b0dc300154 | ||
|
adc998469a | ||
|
4252ed31de | ||
|
279372a784 | ||
|
b77b7cfd62 | ||
|
2553a71b79 | ||
|
5dfcd2a6e4 | ||
|
6f30b395e4 | ||
|
014318a1ba | ||
|
d2c8eea08d | ||
|
4e0d47302b | ||
|
765840cd71 | ||
|
cb4a878fa8 | ||
|
57a585ed46 | ||
|
949338ff18 | ||
|
50fbbe91d8 | ||
|
e88227b506 | ||
|
410f2ce8d4 | ||
|
4e2e758f58 | ||
|
9cb8ee086f | ||
|
a054a570c1 | ||
|
219dc523ec | ||
|
5da882293d | ||
|
868a870a59 | ||
|
10c6233029 | ||
|
bcfe1be681 | ||
|
966786e7f9 | ||
|
087471a232 | ||
|
06bd43d5b5 | ||
|
1758d44e4c | ||
|
1c13ec0888 | ||
|
cc7eb56f51 | ||
|
eb64ae8daa | ||
|
a3c8c2125a | ||
|
3aa419463c | ||
|
e4ba116d7e | ||
|
864a0c80dd | ||
|
be736e5088 | ||
|
48294c483f | ||
|
13e73d6a78 | ||
|
20a517cc3d | ||
|
65d412c840 | ||
|
d031d4719f | ||
|
c1979bcaf5 | ||
|
0adb1fb212 | ||
|
7410cb1733 | ||
|
2d087d0003 | ||
|
ca7a01a593 | ||
|
314a6634d4 | ||
|
6cbc1e6775 | ||
|
81e1cfe301 | ||
|
eb8aa36854 | ||
|
e210c5728d | ||
|
4046186a2d | ||
|
01b73a8bfa | ||
|
c85abde6b0 | ||
|
e9523962ae | ||
|
4e5d067ba8 | ||
|
827206ec57 | ||
|
0cdad6421d | ||
|
f7f7e0183d | ||
|
f901988e57 | ||
|
22d150a1a9 | ||
|
fb17bf685e | ||
|
052ebd1946 | ||
|
028bb2cee8 | ||
|
9fe6885078 | ||
|
6e5a382b6b | ||
|
87272703c2 | ||
|
1c097b5764 | ||
|
014181e1f9 | ||
|
0b9547ddad | ||
|
b104d85d95 | ||
|
e92d79c0a6 | ||
|
2b5869882a | ||
|
1f86907a3d | ||
|
685b40cc1b | ||
|
dcfb8489c6 | ||
|
6218c52c1a | ||
|
c2b6e96cd7 | ||
|
b062d84d36 | ||
|
68fb786d4d | ||
|
f7275b7f45 | ||
|
edf02ab0f9 | ||
|
5b316e6e90 | ||
|
7ed8583a9c | ||
|
6474847481 | ||
|
75003f734f | ||
|
79e6fcdd61 | ||
|
4341446e04 | ||
|
9c18322e85 | ||
|
49095c3236 | ||
|
fff61ab5d6 | ||
|
aef27128f2 | ||
|
c1d72af0a4 | ||
|
0e78e219f5 | ||
|
2e469dd7f3 | ||
|
d9296befa8 | ||
|
f321ce404f | ||
|
67d897a533 | ||
|
e462f17c2d | ||
|
b8390aeffb | ||
|
9dafc01024 | ||
|
7d51c868eb | ||
|
0b0b7af05b | ||
|
7bd389c95e | ||
|
1cae5c5696 | ||
|
369fdbe38d | ||
|
43b37d4f28 | ||
|
a048cfb56d | ||
|
070a3a9f1a | ||
|
d03ef3db5c | ||
|
6d97c2b89e | ||
|
7484d4da41 | ||
|
2964ed2379 | ||
|
a7668291d2 | ||
|
ffc48e63d8 | ||
|
bcc9e50a54 | ||
|
8812114601 | ||
|
5b817ba04d | ||
|
6db55f7dfd | ||
|
61de342adc | ||
|
7f760526ab | ||
|
478a819cb5 | ||
|
902ca6fdf3 | ||
|
074882976f | ||
|
c1820b4a27 | ||
|
8096b7d324 | ||
|
bdcab9df47 | ||
|
8f99919102 | ||
|
27898b0823 | ||
|
47ee1e09e9 | ||
|
4dda1b5fbb | ||
|
585de501da | ||
|
420626d6d9 | ||
|
ab99c8f7aa | ||
|
0eb6ad145d | ||
|
1d314c5668 | ||
|
5b7d3c08ab | ||
|
f770e53989 | ||
|
c4d07defcd | ||
|
65e616c90b | ||
|
f90b418460 | ||
|
bd2474e7f3 | ||
|
a88d8b5b29 | ||
|
213c00aed7 | ||
|
52d976fde2 | ||
|
a6031ff8e2 | ||
|
239fe204de | ||
|
e75fa9329b | ||
|
3b16e1cc3e | ||
|
392b3c76f0 | ||
|
dea4e8129d | ||
|
0dfb4dad0f | ||
|
aec76051f8 | ||
|
8f2e6d04de | ||
|
8d9c4df71a | ||
|
b18f68324f | ||
|
aeadd6aeff | ||
|
3c47079f4d | ||
|
ca9cb71e86 | ||
|
ba98b8c33f | ||
|
3160cbb2e3 | ||
|
bfa3752ad7 | ||
|
e9010baaf5 | ||
|
b530ffcae5 | ||
|
7f42d987e7 | ||
|
469015992a | ||
|
33b18c7da0 | ||
|
596adfc69a | ||
|
e99e722fa5 | ||
|
7ef8fa4a19 | ||
|
9081dc5573 | ||
|
0043228495 | ||
|
6bdd3fde65 | ||
|
3568e093bb | ||
|
acb29ad6f3 | ||
|
d2c1ed0ed5 | ||
|
0085752a56 | ||
|
d7ad42724d | ||
|
83d3f07b0d | ||
|
994f39f9b0 | ||
|
f45dd4d955 | ||
|
b4abcdb016 | ||
|
25cf644f60 | ||
|
71ef7850ab | ||
|
40c0ddcbd6 | ||
|
687d31b7c8 | ||
|
fac6fbe3cf | ||
|
d3b9ee7d24 | ||
|
650537da60 | ||
|
324347b9ec | ||
|
79e675c727 | ||
|
6ef791c715 | ||
|
15ed558a29 | ||
|
106ada7770 | ||
|
9f70f6619f | ||
|
494c0cd2c0 | ||
|
8c058dfeee | ||
|
0807efa91a | ||
|
bea0fc4a37 | ||
|
3f21bac34f | ||
|
7beb91fd0e | ||
|
d1bb87d34e | ||
|
7570340d70 | ||
|
b42acf77b3 | ||
|
1f9c63c34f | ||
|
f8524c42a8 | ||
|
52fbf70879 | ||
|
fb59cd574e | ||
|
c749052162 | ||
|
970e88897c | ||
|
609de5d711 | ||
|
d641b9c436 | ||
|
3bb4e4d2df | ||
|
5ab9a77d50 | ||
|
b80ffbeb3d | ||
|
5f8c2a7ee0 | ||
|
94634cb853 | ||
|
17a07a228e | ||
|
d4bc4c9733 | ||
|
1d7f6b9bfd | ||
|
d718d21d6b | ||
|
39b14fa0d6 | ||
|
19147212a9 | ||
|
53928bcc12 | ||
|
9e568dad6e | ||
|
ebd1788f2c | ||
|
3e2ac10e94 | ||
|
61075bb9df | ||
|
3e61a63f60 | ||
|
a7fbb0a841 | ||
|
1e9e2ed6aa | ||
|
bdc19dee01 | ||
|
3aa720714d | ||
|
94a04e57fb | ||
|
776b33ec09 | ||
|
5595622c3e | ||
|
2ae3e4ba44 | ||
|
b5498d944e | ||
|
8fac3c9f2f | ||
|
a14515a364 | ||
|
190c06e25d | ||
|
62a8a9d6cc | ||
|
48401806f4 | ||
|
02de302774 | ||
|
80597b379e | ||
|
840e9fc96e | ||
|
70367e848e | ||
|
e8daeaee1c | ||
|
3b9ae9fd5f | ||
|
20fedcff2c | ||
|
de38a735ea | ||
|
ce52fb1045 | ||
|
6b787f1cec | ||
|
2185c4f005 | ||
|
6d5f554baa |
270
.travis.yml
270
.travis.yml
@@ -1,4 +1,4 @@
|
||||
# Copyright 2016 Peter Dimov
|
||||
# Copyright 2016, 2017, 2018 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,275 @@ language: cpp
|
||||
|
||||
sudo: false
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
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 VARIANT=debug,release
|
||||
|
||||
- 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 VARIANT=release
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
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 VARIANT=debug,release
|
||||
|
||||
- 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 VARIANT=release
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-5.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-5.0
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-5.0
|
||||
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-5.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-5.0
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-libc++
|
||||
env: TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z VARIANT=release
|
||||
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
|
||||
|
||||
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 ../..
|
||||
- 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:+variant=$VARIANT} ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: always
|
||||
|
@@ -2,5 +2,5 @@
|
||||
|
||||
Branch | Travis | Appveyor
|
||||
---------|--------|---------
|
||||
Develop | [](https://travis-ci.org/boostorg/smart_ptr) | [](https://ci.appveyor.com/project/pdimov/smart_ptr)
|
||||
Master | [](https://travis-ci.org/boostorg/smart_ptr) | [](https://ci.appveyor.com/project/pdimov/smart_ptr)
|
||||
Develop | [](https://travis-ci.org/boostorg/smart_ptr) | [](https://ci.appveyor.com/project/pdimov/smart-ptr)
|
||||
Master | [](https://travis-ci.org/boostorg/smart_ptr) | [](https://ci.appveyor.com/project/pdimov/smart-ptr)
|
||||
|
60
appveyor.yml
60
appveyor.yml
@@ -1,4 +1,4 @@
|
||||
# Copyright 2016 Peter Dimov
|
||||
# Copyright 2016-2018 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,65 @@ branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /feature\/.*/
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0,msvc-12.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
TOOLSET: 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 2013
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
ADDPATH: C:\mingw\bin;
|
||||
TOOLSET: gcc
|
||||
CXXSTD: 03,11,14,1z
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
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
|
||||
- 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
|
||||
|
@@ -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"><boost/smart_ptr.hpp></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<void></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">
|
||||
<boost/detail/atomic_count.hpp></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"><boost/assert.hpp></a>
|
||||
header, the assertions are disabled by default.
|
||||
<li>
|
||||
The partial specialization of <b>std::less</b> has been replaced by <b>operator<</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
2
doc/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/html/
|
||||
/pdf/
|
26
doc/Jamfile
Normal file
26
doc/Jamfile
Normal file
@@ -0,0 +1,26 @@
|
||||
# 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
|
||||
|
||||
project doc/smart_ptr ;
|
||||
|
||||
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 ;
|
6
doc/smart_ptr-docinfo-footer.html
Normal file
6
doc/smart_ptr-docinfo-footer.html
Normal 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>
|
76
doc/smart_ptr.adoc
Normal file
76
doc/smart_ptr.adoc
Normal file
@@ -0,0 +1,76 @@
|
||||
////
|
||||
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/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/make_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].
|
170
doc/smart_ptr/atomic_shared_ptr.adoc
Normal file
170
doc/smart_ptr/atomic_shared_ptr.adoc
Normal 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.
|
144
doc/smart_ptr/enable_shared_from_this.adoc
Normal file
144
doc/smart_ptr/enable_shared_from_this.adoc
Normal file
@@ -0,0 +1,144 @@
|
||||
////
|
||||
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_`.
|
113
doc/smart_ptr/history.adoc
Normal file
113
doc/smart_ptr/history.adoc
Normal file
@@ -0,0 +1,113 @@
|
||||
////
|
||||
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`.
|
49
doc/smart_ptr/introduction.adoc
Normal file
49
doc/smart_ptr/introduction.adoc
Normal file
@@ -0,0 +1,49 @@
|
||||
////
|
||||
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
|
||||
: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`;
|
||||
* `<<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.
|
447
doc/smart_ptr/intrusive_ptr.adoc
Normal file
447
doc/smart_ptr/intrusive_ptr.adoc
Normal file
@@ -0,0 +1,447 @@
|
||||
////
|
||||
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 & operator=(intrusive_ptr const & r);
|
||||
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
|
||||
intrusive_ptr & operator=(T * 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) noexept;
|
||||
};
|
||||
|
||||
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, class U>
|
||||
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> 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()`.
|
||||
|
||||
### 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`.
|
||||
|
||||
### 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, class U>
|
||||
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> 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`.
|
142
doc/smart_ptr/intrusive_ref_counter.adoc
Normal file
142
doc/smart_ptr/intrusive_ref_counter.adoc
Normal file
@@ -0,0 +1,142 @@
|
||||
////
|
||||
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;
|
||||
```
|
||||
::
|
||||
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();
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
Effects::: Does nothing, reference counter is not modified.
|
||||
|
||||
### use_count
|
||||
|
||||
```
|
||||
unsigned int use_count() const noexcept;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
Effects::: Decrements the reference counter. If the reference counter reaches
|
||||
0, calls `delete static_cast<const Derived*>(p)`.
|
719
doc/smart_ptr/local_shared_ptr.adoc
Normal file
719
doc/smart_ptr/local_shared_ptr.adoc
Normal file
@@ -0,0 +1,719 @@
|
||||
////
|
||||
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.
|
||||
|
81
doc/smart_ptr/make_local_shared.adoc
Normal file
81
doc/smart_ptr/make_local_shared.adoc
Normal 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 {
|
||||
`// only if T is not an array type`
|
||||
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);
|
||||
|
||||
`// only if T is an array type of the form U[]`
|
||||
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);
|
||||
|
||||
`// only if T is an array type of the form U[N]`
|
||||
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);
|
||||
|
||||
`// only if T is an array type of the form U[]`
|
||||
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);
|
||||
|
||||
`// only if T is an array type of the form U[N]`
|
||||
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);
|
||||
|
||||
`// only if T is not an array type of the form U[]`
|
||||
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);
|
||||
|
||||
`// only if T is an array type of the form U[N]`
|
||||
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.
|
295
doc/smart_ptr/make_shared.adoc
Normal file
295
doc/smart_ptr/make_shared.adoc
Normal file
@@ -0,0 +1,295 @@
|
||||
////
|
||||
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 {
|
||||
`// only if T is not an array type`
|
||||
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);
|
||||
|
||||
`// only if T is an array type of the form U[]`
|
||||
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);
|
||||
|
||||
`// only if T is an array type of the form U[N]`
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared();
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared(const A& a);
|
||||
|
||||
`// only if T is an array type of the form U[]`
|
||||
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);
|
||||
|
||||
`// only if T is an array type of the form U[N]`
|
||||
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);
|
||||
|
||||
`// only if T is not an array type of the form U[]`
|
||||
template<class T>
|
||||
shared_ptr<T> make_shared_noinit();
|
||||
template<class T, class A>
|
||||
shared_ptr<T> allocate_shared_noinit(const A& a);
|
||||
|
||||
`// only if T is an array type of the form U[N]`
|
||||
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 rebound copy `a` such that its `value_type` is `U`.
|
||||
* 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 rebound copy of `a` such that its value_type is `U`.
|
||||
* 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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is not an array type.
|
||||
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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `U[]`.
|
||||
Returns::: A `shared_ptr` to a sequence of `n` value-initialized objects of
|
||||
type `U`.
|
||||
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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `U[N]`.
|
||||
Returns::: A `shared_ptr` to a sequence of `N` value-initialized objects of
|
||||
type `U`.
|
||||
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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `U[]`.
|
||||
Returns::: A `shared_ptr` to a sequence of `n` objects of type `U`, 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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `U[N]`.
|
||||
Returns::: A `shared_ptr` to a sequence of `N` objects of type `U`, 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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is not an array type, or an array type of the `U[N]`.
|
||||
Returns::: A `shared_ptr` to a default-initialized object of type `T`, or a
|
||||
sequence of `N` default-initialized objects of type `U`, 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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `U[]`.
|
||||
Returns::: A `shared_ptr` to a sequence of `_n_` default-initialized objects
|
||||
of type `U`.
|
||||
Example::: `auto p = make_shared_noinit<double[]>(1024);`
|
115
doc/smart_ptr/make_unique.adoc
Normal file
115
doc/smart_ptr/make_unique.adoc
Normal file
@@ -0,0 +1,115 @@
|
||||
////
|
||||
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 {
|
||||
`// only if T is not an array type`
|
||||
template<class T, class... Args>
|
||||
std::unique_ptr<T> make_unique(Args&&... args);
|
||||
|
||||
`// only if T is not an array type`
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique(remove_reference_t<T>&& v);
|
||||
|
||||
`// only if T is an array type of the form U[]`
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique(std::size_t n);
|
||||
|
||||
`// only if T is not an array type`
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique_noinit();
|
||||
|
||||
`// only if T is an array type of the form U[]`
|
||||
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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is not an array type.
|
||||
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(remove_reference_t<T>&& v);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is not an array type.
|
||||
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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `U[]`.
|
||||
Returns::: `std::unique_ptr<U[]>(new U[n]())`.
|
||||
Example::: `auto p = make_unique<double[]>(1024);`
|
||||
|
||||
```
|
||||
template<class T>
|
||||
std::unique_ptr<T> make_unique_noinit();
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is not an array type.
|
||||
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);
|
||||
```
|
||||
::
|
||||
Remarks::: These overloads shall only participate in overload resolution when
|
||||
`T` is an array type of the form `U[]`.
|
||||
Returns::: `std::unique_ptr<U[]>(new U[n])`.
|
||||
Example::: `auto p = make_unique_noinit<double[]>(1024);`
|
213
doc/smart_ptr/pointer_cast.adoc
Normal file
213
doc/smart_ptr/pointer_cast.adoc
Normal file
@@ -0,0 +1,213 @@
|
||||
////
|
||||
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;
|
||||
```
|
||||
::
|
||||
Returns::: `static_cast<T*>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
Returns::: `dynamic_cast<T*>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
Returns::: `const_cast<T*>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
Returns::: `reinterpret_cast<T*>(p)`
|
||||
|
||||
```
|
||||
template<class T, class U> std::shared_ptr<T>
|
||||
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
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;
|
||||
}
|
||||
```
|
114
doc/smart_ptr/pointer_to_other.adoc
Normal file
114
doc/smart_ptr/pointer_to_other.adoc
Normal 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.
|
175
doc/smart_ptr/scoped_array.adoc
Normal file
175
doc/smart_ptr/scoped_array.adoc
Normal 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`.
|
234
doc/smart_ptr/scoped_ptr.adoc
Normal file
234
doc/smart_ptr/scoped_ptr.adoc
Normal 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)
|
270
doc/smart_ptr/shared_array.adoc
Normal file
270
doc/smart_ptr/shared_array.adoc
Normal file
@@ -0,0 +1,270 @@
|
||||
////
|
||||
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);
|
||||
```
|
||||
::
|
||||
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);
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
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);
|
||||
```
|
||||
::
|
||||
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);
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
Returns::: The stored pointer.
|
||||
|
||||
### unique
|
||||
|
||||
```
|
||||
bool unique() const noexcept;
|
||||
```
|
||||
::
|
||||
Returns::: `true` if no other `shared_array` is sharing ownership of the
|
||||
stored pointer, `false` otherwise.
|
||||
|
||||
### use_count
|
||||
|
||||
```
|
||||
long use_count() const noexcept;
|
||||
```
|
||||
::
|
||||
Returns::: The number of `shared_array` objects sharing ownership of the
|
||||
stored pointer.
|
||||
|
||||
### Conversions
|
||||
|
||||
```
|
||||
explicit operator bool() const noexcept;
|
||||
```
|
||||
::
|
||||
Returns::: `get() != 0`.
|
||||
Requires::: `T` is a complete type.
|
||||
|
||||
### swap
|
||||
|
||||
```
|
||||
void swap(shared_array<T>& b) noexcept;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
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;
|
||||
```
|
||||
::
|
||||
Returns::: `a.swap(b)`.
|
||||
Requires::: `T` is a complete type.
|
1035
doc/smart_ptr/shared_ptr.adoc
Normal file
1035
doc/smart_ptr/shared_ptr.adoc
Normal file
File diff suppressed because it is too large
Load Diff
768
doc/smart_ptr/techniques.adoc
Normal file
768
doc/smart_ptr/techniques.adoc
Normal 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`’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`’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>`’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.
|
298
doc/smart_ptr/weak_ptr.adoc
Normal file
298
doc/smart_ptr/weak_ptr.adoc
Normal file
@@ -0,0 +1,298 @@
|
||||
////
|
||||
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;
|
||||
|
||||
~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;
|
||||
|
||||
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.
|
||||
|
||||
### 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`.
|
||||
|
||||
### 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;
|
||||
}
|
||||
};
|
||||
```
|
@@ -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><boost/enable_shared_from_this.hpp></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<T></code> defines two member functions
|
||||
called <code>shared_from_this</code> that return a <code>shared_ptr<T></code>
|
||||
and <code>shared_ptr<T const></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 <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
|
||||
}
|
||||
</pre>
|
||||
<h2><a name="Synopsis">Synopsis</a></h2>
|
||||
<pre>
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<class T> class enable_shared_from_this
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
</pre>
|
||||
<h4><code>template<class T> shared_ptr<T>
|
||||
enable_shared_from_this<T>::shared_from_this();</code></h4>
|
||||
<h4><code>template<class T> shared_ptr<T const>
|
||||
enable_shared_from_this<T>::shared_from_this() const;</code></h4>
|
||||
<blockquote>
|
||||
<p>
|
||||
<b>Requires:</b> <code>enable_shared_from_this<T></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<T></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<class T> weak_ptr<T>
|
||||
enable_shared_from_this<T>::weak_from_this() noexcept;</code></h4>
|
||||
<h4><code>template<class T> weak_ptr<T const>
|
||||
enable_shared_from_this<T>::weak_from_this() const noexcept;</code></h4>
|
||||
<blockquote>
|
||||
<p>
|
||||
<b>Requires:</b> <code>enable_shared_from_this<T></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<T></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 © 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>
|
@@ -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;
|
@@ -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;
|
@@ -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;
|
@@ -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;
|
BIN
gccspeed.gif
BIN
gccspeed.gif
Binary file not shown.
Before Width: | Height: | Size: 6.4 KiB |
@@ -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 )
|
||||
{
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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>
|
||||
|
||||
|
@@ -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>
|
||||
|
||||
|
@@ -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>
|
||||
|
@@ -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>
|
||||
|
@@ -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
|
||||
|
228
include/boost/smart_ptr/allocate_local_shared_array.hpp
Normal file
228
include/boost/smart_ptr/allocate_local_shared_array.hpp
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
Copyright 2017 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 {
|
||||
|
||||
template<class>
|
||||
struct lsp_if_array { };
|
||||
|
||||
template<class T>
|
||||
struct lsp_if_array<T[]> {
|
||||
typedef boost::local_shared_ptr<T[]> type;
|
||||
};
|
||||
|
||||
template<class>
|
||||
struct lsp_if_size_array { };
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct lsp_if_size_array<T[N]> {
|
||||
typedef boost::local_shared_ptr<T[N]> type;
|
||||
};
|
||||
|
||||
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 detail::lsp_if_array<T>::type
|
||||
allocate_local_shared(const A& allocator, std::size_t count)
|
||||
{
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::lsp_array_state<other> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
std::size_t size = count * detail::sp_array_count<type>::value;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, size, start);
|
||||
detail::lsp_array_base& local = node->state().base();
|
||||
local.set(node);
|
||||
result.release();
|
||||
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), &local);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename detail::lsp_if_size_array<T>::type
|
||||
allocate_local_shared(const A& allocator)
|
||||
{
|
||||
enum {
|
||||
size = detail::sp_array_count<T>::value
|
||||
};
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::lsp_size_array_state<other, size> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, size, start);
|
||||
detail::lsp_array_base& local = node->state().base();
|
||||
local.set(node);
|
||||
result.release();
|
||||
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), &local);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename detail::lsp_if_array<T>::type
|
||||
allocate_local_shared(const A& allocator, std::size_t count,
|
||||
const typename detail::sp_array_element<T>::type& value)
|
||||
{
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::lsp_array_state<other> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
std::size_t size = count * detail::sp_array_count<type>::value;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, size,
|
||||
reinterpret_cast<const scalar*>(&value),
|
||||
detail::sp_array_count<type>::value, start);
|
||||
detail::lsp_array_base& local = node->state().base();
|
||||
local.set(node);
|
||||
result.release();
|
||||
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), &local);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename detail::lsp_if_size_array<T>::type
|
||||
allocate_local_shared(const A& allocator,
|
||||
const typename detail::sp_array_element<T>::type& value)
|
||||
{
|
||||
enum {
|
||||
size = detail::sp_array_count<T>::value
|
||||
};
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::lsp_size_array_state<other, size> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, size,
|
||||
reinterpret_cast<const scalar*>(&value),
|
||||
detail::sp_array_count<type>::value, start);
|
||||
detail::lsp_array_base& local = node->state().base();
|
||||
local.set(node);
|
||||
result.release();
|
||||
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), &local);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename detail::lsp_if_array<T>::type
|
||||
allocate_local_shared_noinit(const A& allocator, std::size_t count)
|
||||
{
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::lsp_array_state<other> state;
|
||||
typedef detail::sp_array_base<state, false> base;
|
||||
std::size_t size = count * detail::sp_array_count<type>::value;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
|
||||
size, start);
|
||||
detail::lsp_array_base& local = node->state().base();
|
||||
local.set(node);
|
||||
result.release();
|
||||
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), &local);
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename detail::lsp_if_size_array<T>::type
|
||||
allocate_local_shared_noinit(const A& allocator)
|
||||
{
|
||||
enum {
|
||||
size = detail::sp_array_count<T>::value
|
||||
};
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::lsp_size_array_state<other, size> state;
|
||||
typedef detail::sp_array_base<state, false> base;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
|
||||
size, start);
|
||||
detail::lsp_array_base& local = node->state().base();
|
||||
local.set(node);
|
||||
result.release();
|
||||
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), &local);
|
||||
}
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif
|
@@ -1,181 +1,648 @@
|
||||
/*
|
||||
* 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-2018 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/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#include <boost/type_traits/has_trivial_assign.hpp>
|
||||
#include <boost/type_traits/has_trivial_constructor.hpp>
|
||||
#include <boost/type_traits/has_trivial_destructor.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>
|
||||
struct sp_if_array { };
|
||||
|
||||
template<class T>
|
||||
struct sp_if_array<T[]> {
|
||||
typedef boost::shared_ptr<T[]> type;
|
||||
};
|
||||
|
||||
template<class>
|
||||
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;
|
||||
};
|
||||
|
||||
template<class>
|
||||
struct sp_array_element { };
|
||||
|
||||
template<class T>
|
||||
struct sp_array_element<T[]> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct sp_array_element<T[N]> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sp_array_scalar {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct sp_array_scalar<T[N]> {
|
||||
typedef typename sp_array_scalar<T>::type type;
|
||||
};
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct sp_array_scalar<const T[N]> {
|
||||
typedef typename sp_array_scalar<T>::type type;
|
||||
};
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct sp_array_scalar<volatile T[N]> {
|
||||
typedef typename sp_array_scalar<T>::type type;
|
||||
};
|
||||
|
||||
template<class T, std::size_t N>
|
||||
struct sp_array_scalar<const volatile T[N]> {
|
||||
typedef typename sp_array_scalar<T>::type type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sp_array_scalar<T[]> {
|
||||
typedef typename sp_array_scalar<T>::type type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sp_array_scalar<const T[]> {
|
||||
typedef typename sp_array_scalar<T>::type type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sp_array_scalar<volatile T[]> {
|
||||
typedef typename sp_array_scalar<T>::type type;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sp_array_scalar<const volatile T[]> {
|
||||
typedef typename sp_array_scalar<T>::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>
|
||||
BOOST_CONSTEXPR inline std::size_t
|
||||
sp_objects(std::size_t size) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return (size + sizeof(T) - 1) / sizeof(T);
|
||||
}
|
||||
|
||||
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<bool, class = void>
|
||||
struct sp_enable { };
|
||||
|
||||
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>
|
||||
struct sp_enable<true, T> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
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<bool E, class A, class T>
|
||||
inline typename sp_enable<!E && boost::has_trivial_destructor<T>::value>::type
|
||||
sp_array_destroy(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
|
||||
|
||||
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<bool E, class A, class T>
|
||||
inline typename sp_enable<!E &&
|
||||
!boost::has_trivial_destructor<T>::value>::type
|
||||
sp_array_destroy(A&, T* ptr, std::size_t size)
|
||||
{
|
||||
while (size > 0) {
|
||||
ptr[--size].~T();
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
template<bool E, class A, class T>
|
||||
inline typename sp_enable<E>::type
|
||||
sp_array_destroy(A& allocator, T* ptr, std::size_t size)
|
||||
{
|
||||
while (size > 0) {
|
||||
std::allocator_traits<A>::destroy(allocator, ptr + --size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template<bool E, class A, class T>
|
||||
class sp_destroyer {
|
||||
public:
|
||||
sp_destroyer(A& allocator, T* ptr) BOOST_SP_NOEXCEPT
|
||||
: allocator_(allocator),
|
||||
ptr_(ptr),
|
||||
size_(0) { }
|
||||
|
||||
~sp_destroyer() {
|
||||
sp_array_destroy<E>(allocator_, ptr_, size_);
|
||||
}
|
||||
|
||||
std::size_t& size() BOOST_SP_NOEXCEPT {
|
||||
return size_;
|
||||
}
|
||||
|
||||
private:
|
||||
sp_destroyer(const sp_destroyer&);
|
||||
sp_destroyer& operator=(const sp_destroyer&);
|
||||
|
||||
A& allocator_;
|
||||
T* ptr_;
|
||||
std::size_t size_;
|
||||
};
|
||||
|
||||
template<bool E, class A, class T>
|
||||
inline typename sp_enable<!E &&
|
||||
boost::has_trivial_constructor<T>::value &&
|
||||
boost::has_trivial_assign<T>::value &&
|
||||
boost::has_trivial_destructor<T>::value>::type
|
||||
sp_array_construct(A&, T* ptr, std::size_t size)
|
||||
{
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
ptr[i] = T();
|
||||
}
|
||||
}
|
||||
|
||||
template<bool E, class A, class T>
|
||||
inline typename sp_enable<!E &&
|
||||
boost::has_trivial_constructor<T>::value &&
|
||||
boost::has_trivial_assign<T>::value &&
|
||||
boost::has_trivial_destructor<T>::value>::type
|
||||
sp_array_construct(A&, T* ptr, std::size_t size, const T* list,
|
||||
std::size_t count)
|
||||
{
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
ptr[i] = list[i % count];
|
||||
}
|
||||
}
|
||||
|
||||
template<bool E, class A, class T>
|
||||
inline typename sp_enable<!E &&
|
||||
!(boost::has_trivial_constructor<T>::value &&
|
||||
boost::has_trivial_assign<T>::value &&
|
||||
boost::has_trivial_destructor<T>::value)>::type
|
||||
sp_array_construct(A& none, T* ptr, std::size_t size)
|
||||
{
|
||||
sp_destroyer<E, A, T> hold(none, ptr);
|
||||
for (std::size_t& i = hold.size(); i < size; ++i) {
|
||||
::new(static_cast<void*>(ptr + i)) T();
|
||||
}
|
||||
hold.size() = 0;
|
||||
}
|
||||
|
||||
template<bool E, class A, class T>
|
||||
inline typename sp_enable<!E &&
|
||||
!(boost::has_trivial_constructor<T>::value &&
|
||||
boost::has_trivial_assign<T>::value &&
|
||||
boost::has_trivial_destructor<T>::value)>::type
|
||||
sp_array_construct(A& none, T* ptr, std::size_t size, const T* list,
|
||||
std::size_t count)
|
||||
{
|
||||
sp_destroyer<E, A, T> hold(none, ptr);
|
||||
for (std::size_t& i = hold.size(); i < size; ++i) {
|
||||
::new(static_cast<void*>(ptr + i)) T(list[i % count]);
|
||||
}
|
||||
hold.size() = 0;
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
template<bool E, class A, class T>
|
||||
inline typename sp_enable<E>::type
|
||||
sp_array_construct(A& allocator, T* ptr, std::size_t size)
|
||||
{
|
||||
sp_destroyer<E, A, T> hold(allocator, ptr);
|
||||
for (std::size_t& i = hold.size(); i < size; ++i) {
|
||||
std::allocator_traits<A>::construct(allocator, ptr + i);
|
||||
}
|
||||
hold.size() = 0;
|
||||
}
|
||||
|
||||
template<bool E, class A, class T>
|
||||
inline typename sp_enable<E>::type
|
||||
sp_array_construct(A& allocator, T* ptr, std::size_t size, const T* list,
|
||||
std::size_t count)
|
||||
{
|
||||
sp_destroyer<E, A, T> hold(allocator, ptr);
|
||||
for (std::size_t& i = hold.size(); i < size; ++i) {
|
||||
std::allocator_traits<A>::construct(allocator, ptr + i,
|
||||
list[i % count]);
|
||||
}
|
||||
hold.size() = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class A, class T>
|
||||
inline typename sp_enable<boost::has_trivial_constructor<T>::value>::type
|
||||
sp_array_default(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
|
||||
|
||||
template<class A, class T>
|
||||
inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
|
||||
sp_array_default(A& none, T* ptr, std::size_t size)
|
||||
{
|
||||
sp_destroyer<false, A, T> hold(none, ptr);
|
||||
for (std::size_t& i = hold.size(); i < size; ++i) {
|
||||
::new(static_cast<void*>(ptr + i)) T;
|
||||
}
|
||||
hold.size() = 0;
|
||||
}
|
||||
|
||||
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_;
|
||||
};
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
template<class A>
|
||||
struct sp_use_construct {
|
||||
enum {
|
||||
value = true
|
||||
};
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct sp_use_construct<std::allocator<T> > {
|
||||
enum {
|
||||
value = false
|
||||
};
|
||||
};
|
||||
#else
|
||||
template<class>
|
||||
struct sp_use_construct {
|
||||
enum {
|
||||
value = false
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
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 T, class U>
|
||||
struct sp_array_storage {
|
||||
enum {
|
||||
value = sp_array_alignment<T, U>::value
|
||||
};
|
||||
typedef typename boost::type_with_alignment<value>::type type;
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
inline U*
|
||||
sp_array_start(void* base) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
enum {
|
||||
size = sp_array_offset<T, U>::value
|
||||
};
|
||||
return reinterpret_cast<U*>(static_cast<char*>(base) + size);
|
||||
}
|
||||
|
||||
template<class A, class T>
|
||||
class sp_array_creator {
|
||||
typedef typename A::value_type scalar;
|
||||
|
||||
enum {
|
||||
offset = sp_array_offset<T, scalar>::value
|
||||
};
|
||||
|
||||
typedef typename sp_array_storage<T, scalar>::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(scalar) * 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_;
|
||||
};
|
||||
|
||||
struct sp_default { };
|
||||
|
||||
template<class T, bool E = sp_use_construct<T>::value>
|
||||
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, std::size_t size, type* start)
|
||||
: state_(other, size) {
|
||||
sp_array_construct<E>(state_.allocator(), start, state_.size());
|
||||
}
|
||||
|
||||
template<class A>
|
||||
sp_array_base(const A& other, std::size_t size, const type* list,
|
||||
std::size_t count, type* start)
|
||||
: state_(other, size) {
|
||||
sp_array_construct<E>(state_.allocator(), start, state_.size(), list,
|
||||
count);
|
||||
}
|
||||
|
||||
template<class A>
|
||||
sp_array_base(sp_default, const A& other, std::size_t size, type* start)
|
||||
: state_(other, size) {
|
||||
sp_array_default(state_.allocator(), start, state_.size());
|
||||
}
|
||||
|
||||
T& state() BOOST_SP_NOEXCEPT {
|
||||
return state_;
|
||||
}
|
||||
|
||||
virtual void dispose() {
|
||||
sp_array_destroy<E>(state_.allocator(),
|
||||
sp_array_start<sp_array_base, type>(this), state_.size());
|
||||
}
|
||||
|
||||
virtual void destroy() {
|
||||
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&) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void* get_local_deleter(const sp_typeinfo&) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void* get_untyped_deleter() {
|
||||
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 {
|
||||
return result_;
|
||||
}
|
||||
|
||||
void release() {
|
||||
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 detail::sp_if_array<T>::type
|
||||
allocate_shared(const A& allocator, std::size_t count)
|
||||
{
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::sp_array_state<other> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
std::size_t size = count * detail::sp_array_count<type>::value;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
detail::sp_counted_base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, size, start);
|
||||
result.release();
|
||||
return shared_ptr<T>(detail::sp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), detail::shared_count(node));
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename detail::sp_if_size_array<T>::type
|
||||
allocate_shared(const A& allocator)
|
||||
{
|
||||
enum {
|
||||
size = detail::sp_array_count<T>::value
|
||||
};
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::sp_size_array_state<other, size> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
detail::sp_counted_base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, size, start);
|
||||
result.release();
|
||||
return shared_ptr<T>(detail::sp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), detail::shared_count(node));
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename detail::sp_if_array<T>::type
|
||||
allocate_shared(const A& allocator, std::size_t count,
|
||||
const typename detail::sp_array_element<T>::type& value)
|
||||
{
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::sp_array_state<other> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
std::size_t size = count * detail::sp_array_count<type>::value;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
detail::sp_counted_base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, size,
|
||||
reinterpret_cast<const scalar*>(&value),
|
||||
detail::sp_array_count<type>::value, start);
|
||||
result.release();
|
||||
return shared_ptr<T>(detail::sp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), detail::shared_count(node));
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename detail::sp_if_size_array<T>::type
|
||||
allocate_shared(const A& allocator,
|
||||
const typename detail::sp_array_element<T>::type& value)
|
||||
{
|
||||
enum {
|
||||
size = detail::sp_array_count<T>::value
|
||||
};
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::sp_size_array_state<other, size> state;
|
||||
typedef detail::sp_array_base<state> base;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
detail::sp_counted_base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(allocator, size,
|
||||
reinterpret_cast<const scalar*>(&value),
|
||||
detail::sp_array_count<type>::value, start);
|
||||
result.release();
|
||||
return shared_ptr<T>(detail::sp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), detail::shared_count(node));
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename detail::sp_if_array<T>::type
|
||||
allocate_shared_noinit(const A& allocator, std::size_t count)
|
||||
{
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::sp_array_state<other> state;
|
||||
typedef detail::sp_array_base<state, false> base;
|
||||
std::size_t size = count * detail::sp_array_count<type>::value;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
detail::sp_counted_base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
|
||||
size, start);
|
||||
result.release();
|
||||
return shared_ptr<T>(detail::sp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), detail::shared_count(node));
|
||||
}
|
||||
|
||||
template<class T, class A>
|
||||
inline typename detail::sp_if_size_array<T>::type
|
||||
allocate_shared_noinit(const A& allocator)
|
||||
{
|
||||
enum {
|
||||
size = detail::sp_array_count<T>::value
|
||||
};
|
||||
typedef typename detail::sp_array_element<T>::type type;
|
||||
typedef typename detail::sp_array_scalar<T>::type scalar;
|
||||
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
|
||||
typedef detail::sp_size_array_state<other, size> state;
|
||||
typedef detail::sp_array_base<state, false> base;
|
||||
detail::sp_array_result<other, base> result(allocator, size);
|
||||
detail::sp_counted_base* node = result.get();
|
||||
scalar* start = detail::sp_array_start<base, scalar>(node);
|
||||
::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
|
||||
size, start);
|
||||
result.release();
|
||||
return shared_ptr<T>(detail::sp_internal_constructor_tag(),
|
||||
reinterpret_cast<type*>(start), detail::shared_count(node));
|
||||
}
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif
|
||||
|
233
include/boost/smart_ptr/atomic_shared_ptr.hpp
Normal file
233
include/boost/smart_ptr/atomic_shared_ptr.hpp
Normal file
@@ -0,0 +1,233 @@
|
||||
#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
|
||||
{
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
atomic_shared_ptr() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT;
|
||||
std::memcpy( &l_, &init, sizeof( init ) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
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 ) );
|
||||
}
|
||||
|
||||
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
|
@@ -17,6 +17,7 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <exception>
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
@@ -36,6 +37,12 @@ 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:
|
||||
@@ -46,6 +53,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_CLANG)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#if defined(__BORLANDC__) && __BORLANDC__ <= 0x564
|
||||
# pragma option pop
|
||||
#endif
|
||||
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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>
|
||||
|
||||
|
@@ -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
|
||||
|
148
include/boost/smart_ptr/detail/local_counted_base.hpp
Normal file
148
include/boost/smart_ptr/detail/local_counted_base.hpp
Normal 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 ): pn_( pn )
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
explicit local_counted_impl( shared_count && pn ): 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
|
91
include/boost/smart_ptr/detail/local_sp_deleter.hpp
Normal file
91
include/boost/smart_ptr/detail/local_sp_deleter.hpp
Normal 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()
|
||||
{
|
||||
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 )
|
||||
{
|
||||
return &p->deleter();
|
||||
}
|
||||
|
||||
inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED
|
@@ -21,7 +21,13 @@
|
||||
#include <boost/predef.h>
|
||||
|
||||
#ifdef BOOST_USE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#else
|
||||
|
||||
struct _RTL_CRITICAL_SECTION;
|
||||
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
@@ -47,18 +53,31 @@ struct critical_section
|
||||
};
|
||||
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSectionEx(critical_section *, unsigned long, unsigned long);
|
||||
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSectionEx(::_RTL_CRITICAL_SECTION *, unsigned long, unsigned long);
|
||||
#else
|
||||
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *);
|
||||
extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_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 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;
|
||||
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
using ::InitializeCriticalSectionEx;
|
||||
#else
|
||||
using ::InitializeCriticalSection;
|
||||
#endif
|
||||
using ::EnterCriticalSection;
|
||||
using ::LeaveCriticalSection;
|
||||
using ::DeleteCriticalSection;
|
||||
|
||||
typedef ::CRITICAL_SECTION rtl_critical_section;
|
||||
|
||||
#endif // #ifndef BOOST_USE_WINDOWS_H
|
||||
|
||||
class lightweight_mutex
|
||||
@@ -75,15 +94,15 @@ public:
|
||||
lightweight_mutex()
|
||||
{
|
||||
#if BOOST_PLAT_WINDOWS_RUNTIME
|
||||
InitializeCriticalSectionEx(&cs_, 4000, 0);
|
||||
boost::detail::InitializeCriticalSectionEx(reinterpret_cast< rtl_critical_section* >(&cs_), 4000, 0);
|
||||
#else
|
||||
InitializeCriticalSection(&cs_);
|
||||
boost::detail::InitializeCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_));
|
||||
#endif
|
||||
}
|
||||
|
||||
~lightweight_mutex()
|
||||
{
|
||||
DeleteCriticalSection(&cs_);
|
||||
boost::detail::DeleteCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_));
|
||||
}
|
||||
|
||||
class scoped_lock;
|
||||
@@ -102,12 +121,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_));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -54,7 +54,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 +118,14 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
shared_count(): pi_(0) // nothrow
|
||||
BOOST_CONSTEXPR shared_count(): pi_(0) // nothrow
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ): pi_( pi ) // nothrow
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(shared_count_id)
|
||||
#endif
|
||||
@@ -249,18 +256,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 +273,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 +313,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 +330,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
|
||||
{
|
||||
@@ -550,6 +503,11 @@ public:
|
||||
return pi_? pi_->get_deleter( ti ): 0;
|
||||
}
|
||||
|
||||
void * get_local_deleter( sp_typeinfo const & ti ) const
|
||||
{
|
||||
return pi_? pi_->get_local_deleter( ti ): 0;
|
||||
}
|
||||
|
||||
void * get_untyped_deleter() const
|
||||
{
|
||||
return pi_? pi_->get_untyped_deleter(): 0;
|
||||
@@ -571,7 +529,7 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
weak_count(): pi_(0) // nothrow
|
||||
BOOST_CONSTEXPR weak_count(): pi_(0) // nothrow
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
, id_(weak_count_id)
|
||||
#endif
|
||||
|
@@ -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 )
|
||||
|
@@ -16,6 +16,7 @@
|
||||
//
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -104,6 +105,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -21,6 +21,7 @@
|
||||
//
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -96,6 +97,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/detail/sp_typeinfo.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
|
||||
namespace boost
|
||||
@@ -58,15 +59,20 @@ 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:
|
||||
|
||||
@@ -93,6 +99,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
@@ -133,6 +140,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
@@ -25,6 +25,7 @@
|
||||
//
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -124,6 +125,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -26,6 +26,7 @@
|
||||
//
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -112,6 +113,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -17,6 +17,7 @@
|
||||
//
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -111,6 +112,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -21,6 +21,7 @@
|
||||
//
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -135,6 +142,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -25,6 +25,7 @@
|
||||
//
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -135,6 +136,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -20,6 +20,7 @@
|
||||
// Thanks to Michael van der Westhuizen
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -120,6 +121,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -25,6 +25,7 @@
|
||||
//
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -127,6 +128,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -19,6 +19,7 @@
|
||||
//
|
||||
|
||||
#include <boost/detail/sp_typeinfo.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
@@ -26,7 +27,7 @@ namespace boost
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class sp_counted_base
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -59,6 +60,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <boost/detail/sp_typeinfo.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <pthread.h>
|
||||
|
||||
namespace boost
|
||||
@@ -28,7 +29,7 @@ namespace boost
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class sp_counted_base
|
||||
class BOOST_SYMBOL_VISIBLE sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -71,6 +72,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -20,6 +20,7 @@
|
||||
// Thanks to Michael van der Westhuizen
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -115,6 +116,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -21,6 +21,7 @@
|
||||
//
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -62,6 +63,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -84,6 +85,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/detail/sp_typeinfo.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
@@ -57,15 +58,15 @@ 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:
|
||||
|
||||
@@ -90,6 +91,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -16,6 +16,7 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -109,6 +110,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -22,6 +22,7 @@
|
||||
//
|
||||
|
||||
#include <boost/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:
|
||||
|
||||
@@ -104,6 +105,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include <boost/smart_ptr/detail/sp_interlocked.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/detail/sp_typeinfo.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:
|
||||
|
||||
@@ -67,6 +68,7 @@ public:
|
||||
}
|
||||
|
||||
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()
|
||||
|
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
|
||||
#include <boost/core/addressof.hpp>
|
||||
|
||||
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
|
||||
#include <boost/smart_ptr/detail/quick_allocator.hpp>
|
||||
@@ -50,7 +51,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*/ )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class D> D * get_local_deleter( local_sp_deleter<D> * p );
|
||||
|
||||
//
|
||||
|
||||
template<class X> class BOOST_SYMBOL_VISIBLE sp_counted_impl_p: public sp_counted_base
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -83,6 +97,11 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void * get_local_deleter( sp_typeinfo const & )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual void * get_untyped_deleter()
|
||||
{
|
||||
return 0;
|
||||
@@ -124,7 +143,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:
|
||||
|
||||
@@ -158,6 +177,11 @@ public:
|
||||
return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
|
||||
}
|
||||
|
||||
virtual void * get_local_deleter( sp_typeinfo const & ti )
|
||||
{
|
||||
return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0;
|
||||
}
|
||||
|
||||
virtual void * get_untyped_deleter()
|
||||
{
|
||||
return &reinterpret_cast<char&>( del );
|
||||
@@ -192,7 +216,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:
|
||||
|
||||
@@ -236,16 +260,8 @@ 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 );
|
||||
}
|
||||
|
||||
@@ -254,6 +270,11 @@ public:
|
||||
return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;
|
||||
}
|
||||
|
||||
virtual void * get_local_deleter( sp_typeinfo const & ti )
|
||||
{
|
||||
return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0;
|
||||
}
|
||||
|
||||
virtual void * get_untyped_deleter()
|
||||
{
|
||||
return &reinterpret_cast<char&>( d_ );
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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
|
@@ -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 )
|
||||
|
48
include/boost/smart_ptr/detail/sp_noexcept.hpp
Normal file
48
include/boost/smart_ptr/detail/sp_noexcept.hpp
Normal 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
|
@@ -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>
|
||||
|
||||
|
@@ -33,7 +33,7 @@
|
||||
|
||||
// BOOST_SMT_PAUSE
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) )
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) && !defined(__c2__)
|
||||
|
||||
extern "C" void _mm_pause();
|
||||
|
||||
@@ -60,18 +60,24 @@ namespace detail
|
||||
{
|
||||
|
||||
#if !defined( BOOST_USE_WINDOWS_H ) && !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
#if !BOOST_COMP_CLANG || !defined __MINGW32__
|
||||
extern "C" void __stdcall Sleep( unsigned long ms );
|
||||
|
||||
#if defined(__clang__) && defined(__x86_64__)
|
||||
// clang x64 warns that __stdcall is ignored
|
||||
# define BOOST_SP_STDCALL
|
||||
#else
|
||||
#include <_mingw.h>
|
||||
#if !defined __MINGW64_VERSION_MAJOR
|
||||
extern "C" void __stdcall Sleep( unsigned long ms );
|
||||
# define BOOST_SP_STDCALL __stdcall
|
||||
#endif
|
||||
|
||||
#if defined(__LP64__) // Cygwin 64
|
||||
extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned int ms );
|
||||
#else
|
||||
extern "C" __declspec(dllimport) void __stdcall Sleep( unsigned long ms );
|
||||
#endif
|
||||
#endif
|
||||
extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned long ms );
|
||||
#endif
|
||||
|
||||
#undef BOOST_SP_STDCALL
|
||||
|
||||
#endif // !defined( BOOST_USE_WINDOWS_H ) && !BOOST_PLAT_WINDOWS_RUNTIME
|
||||
|
||||
inline void yield( unsigned k )
|
||||
{
|
||||
if( k < 4 )
|
||||
|
@@ -10,11 +10,12 @@
|
||||
// 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/weak_ptr.hpp>
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
@@ -25,20 +26,20 @@ template<class T> class enable_shared_from_this
|
||||
{
|
||||
protected:
|
||||
|
||||
enable_shared_from_this() BOOST_NOEXCEPT
|
||||
BOOST_CONSTEXPR enable_shared_from_this() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
enable_shared_from_this(enable_shared_from_this const &) BOOST_NOEXCEPT
|
||||
BOOST_CONSTEXPR enable_shared_from_this(enable_shared_from_this const &) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
}
|
||||
|
||||
enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_NOEXCEPT
|
||||
enable_shared_from_this & operator=(enable_shared_from_this const &) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
~enable_shared_from_this() BOOST_NOEXCEPT // ~weak_ptr<T> newer throws, so this call also must not throw
|
||||
~enable_shared_from_this() BOOST_SP_NOEXCEPT // ~weak_ptr<T> newer throws, so this call also must not throw
|
||||
{
|
||||
}
|
||||
|
||||
@@ -58,12 +59,12 @@ public:
|
||||
return p;
|
||||
}
|
||||
|
||||
weak_ptr<T> weak_from_this() BOOST_NOEXCEPT
|
||||
weak_ptr<T> weak_from_this() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return weak_this_;
|
||||
}
|
||||
|
||||
weak_ptr<T const> weak_from_this() const BOOST_NOEXCEPT
|
||||
weak_ptr<T const> weak_from_this() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return weak_this_;
|
||||
}
|
||||
@@ -71,7 +72,7 @@ public:
|
||||
public: // actually private, but avoids compiler template friendship issues
|
||||
|
||||
// Note: invoked automatically by shared_ptr; do not call
|
||||
template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const
|
||||
template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
if( weak_this_.expired() )
|
||||
{
|
||||
|
@@ -6,11 +6,11 @@
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
// Distributed under the Boost Software License, Version 1.0. (See
|
||||
// accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation.
|
||||
// See http://www.boost.org/libs/smart_ptr/ for documentation.
|
||||
//
|
||||
|
||||
#include <boost/config.hpp>
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_convertible.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
|
||||
|
||||
#include <boost/config/no_tr1/functional.hpp> // for std::less
|
||||
|
||||
@@ -59,7 +60,7 @@ public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
BOOST_CONSTEXPR intrusive_ptr() BOOST_NOEXCEPT : px( 0 )
|
||||
BOOST_CONSTEXPR intrusive_ptr() BOOST_SP_NOEXCEPT : px( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -111,12 +112,12 @@ public:
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
intrusive_ptr(intrusive_ptr && rhs) BOOST_NOEXCEPT : px( rhs.px )
|
||||
intrusive_ptr(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT : px( rhs.px )
|
||||
{
|
||||
rhs.px = 0;
|
||||
}
|
||||
|
||||
intrusive_ptr & operator=(intrusive_ptr && rhs) BOOST_NOEXCEPT
|
||||
intrusive_ptr & operator=(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
|
||||
return *this;
|
||||
@@ -140,7 +141,7 @@ public:
|
||||
}
|
||||
|
||||
template<class U>
|
||||
intrusive_ptr & operator=(intrusive_ptr<U> && rhs) BOOST_NOEXCEPT
|
||||
intrusive_ptr & operator=(intrusive_ptr<U> && rhs) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);
|
||||
return *this;
|
||||
@@ -160,7 +161,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset() BOOST_NOEXCEPT
|
||||
void reset()
|
||||
{
|
||||
this_type().swap( *this );
|
||||
}
|
||||
@@ -175,25 +176,25 @@ public:
|
||||
this_type( rhs, add_ref ).swap( *this );
|
||||
}
|
||||
|
||||
T * get() const BOOST_NOEXCEPT
|
||||
T * get() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return px;
|
||||
}
|
||||
|
||||
T * detach() BOOST_NOEXCEPT
|
||||
T * detach() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
T * ret = px;
|
||||
px = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
T & operator*() const
|
||||
T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
|
||||
{
|
||||
BOOST_ASSERT( px != 0 );
|
||||
return *px;
|
||||
}
|
||||
|
||||
T * operator->() const
|
||||
T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
|
||||
{
|
||||
BOOST_ASSERT( px != 0 );
|
||||
return px;
|
||||
@@ -202,7 +203,7 @@ public:
|
||||
// implicit conversion to "bool"
|
||||
#include <boost/smart_ptr/detail/operator_bool.hpp>
|
||||
|
||||
void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT
|
||||
void swap(intrusive_ptr & rhs) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
T * tmp = px;
|
||||
px = rhs.px;
|
||||
@@ -214,32 +215,32 @@ private:
|
||||
T * px;
|
||||
};
|
||||
|
||||
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
|
||||
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b)
|
||||
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b)
|
||||
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.get() == b;
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b)
|
||||
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.get() != b;
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b)
|
||||
template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a == b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b)
|
||||
template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a != b.get();
|
||||
}
|
||||
@@ -248,7 +249,7 @@ template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const
|
||||
|
||||
// Resolve the ambiguity between our op!= and the one in rel_ops
|
||||
|
||||
template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
|
||||
template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
@@ -257,41 +258,41 @@ template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_p
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_NULLPTR )
|
||||
|
||||
template<class T> inline bool operator==( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
|
||||
template<class T> inline bool operator==( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get() == 0;
|
||||
}
|
||||
|
||||
template<class T> inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_NOEXCEPT
|
||||
template<class T> inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get() == 0;
|
||||
}
|
||||
|
||||
template<class T> inline bool operator!=( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
|
||||
template<class T> inline bool operator!=( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get() != 0;
|
||||
}
|
||||
|
||||
template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_NOEXCEPT
|
||||
template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get() != 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b)
|
||||
template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return std::less<T *>()(a.get(), b.get());
|
||||
}
|
||||
|
||||
template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs)
|
||||
template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
// mem_fn support
|
||||
|
||||
template<class T> T * get_pointer(intrusive_ptr<T> const & p)
|
||||
template<class T> T * get_pointer(intrusive_ptr<T> const & p) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get();
|
||||
}
|
||||
@@ -350,7 +351,7 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::
|
||||
|
||||
template< class T > struct hash;
|
||||
|
||||
template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p )
|
||||
template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return boost::hash< T* >()( p.get() );
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/smart_ptr/detail/atomic_count.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_PRAGMA_ONCE
|
||||
#pragma once
|
||||
@@ -45,17 +46,17 @@ struct thread_unsafe_counter
|
||||
{
|
||||
typedef unsigned int type;
|
||||
|
||||
static unsigned int load(unsigned int const& counter) BOOST_NOEXCEPT
|
||||
static unsigned int load(unsigned int const& counter) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return counter;
|
||||
}
|
||||
|
||||
static void increment(unsigned int& counter) BOOST_NOEXCEPT
|
||||
static void increment(unsigned int& counter) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
++counter;
|
||||
}
|
||||
|
||||
static unsigned int decrement(unsigned int& counter) BOOST_NOEXCEPT
|
||||
static unsigned int decrement(unsigned int& counter) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return --counter;
|
||||
}
|
||||
@@ -71,17 +72,17 @@ struct thread_safe_counter
|
||||
{
|
||||
typedef boost::detail::atomic_count type;
|
||||
|
||||
static unsigned int load(boost::detail::atomic_count const& counter) BOOST_NOEXCEPT
|
||||
static unsigned int load(boost::detail::atomic_count const& counter) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return static_cast< unsigned int >(static_cast< long >(counter));
|
||||
}
|
||||
|
||||
static void increment(boost::detail::atomic_count& counter) BOOST_NOEXCEPT
|
||||
static void increment(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
++counter;
|
||||
}
|
||||
|
||||
static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_NOEXCEPT
|
||||
static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return static_cast< unsigned int >(--counter);
|
||||
}
|
||||
@@ -91,9 +92,9 @@ template< typename DerivedT, typename CounterPolicyT = thread_safe_counter >
|
||||
class intrusive_ref_counter;
|
||||
|
||||
template< typename DerivedT, typename CounterPolicyT >
|
||||
void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
|
||||
void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
|
||||
template< typename DerivedT, typename CounterPolicyT >
|
||||
void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
|
||||
void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
|
||||
|
||||
/*!
|
||||
* \brief A reference counter base class
|
||||
@@ -121,7 +122,7 @@ public:
|
||||
*
|
||||
* \post <tt>use_count() == 0</tt>
|
||||
*/
|
||||
intrusive_ref_counter() BOOST_NOEXCEPT : m_ref_counter(0)
|
||||
intrusive_ref_counter() BOOST_SP_NOEXCEPT : m_ref_counter(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -130,7 +131,7 @@ public:
|
||||
*
|
||||
* \post <tt>use_count() == 0</tt>
|
||||
*/
|
||||
intrusive_ref_counter(intrusive_ref_counter const&) BOOST_NOEXCEPT : m_ref_counter(0)
|
||||
intrusive_ref_counter(intrusive_ref_counter const&) BOOST_SP_NOEXCEPT : m_ref_counter(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -139,12 +140,12 @@ public:
|
||||
*
|
||||
* \post The reference counter is not modified after assignment
|
||||
*/
|
||||
intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_NOEXCEPT { return *this; }
|
||||
intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_SP_NOEXCEPT { return *this; }
|
||||
|
||||
/*!
|
||||
* \return The reference counter
|
||||
*/
|
||||
unsigned int use_count() const BOOST_NOEXCEPT
|
||||
unsigned int use_count() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return CounterPolicyT::load(m_ref_counter);
|
||||
}
|
||||
@@ -155,18 +156,18 @@ protected:
|
||||
*/
|
||||
BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {})
|
||||
|
||||
friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
|
||||
friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
|
||||
friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
|
||||
friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
|
||||
};
|
||||
|
||||
template< typename DerivedT, typename CounterPolicyT >
|
||||
inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT
|
||||
inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
CounterPolicyT::increment(p->m_ref_counter);
|
||||
}
|
||||
|
||||
template< typename DerivedT, typename CounterPolicyT >
|
||||
inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT
|
||||
inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
if (CounterPolicyT::decrement(p->m_ref_counter) == 0)
|
||||
delete static_cast< const DerivedT* >(p);
|
||||
|
684
include/boost/smart_ptr/local_shared_ptr.hpp
Normal file
684
include/boost/smart_ptr/local_shared_ptr.hpp
Normal file
@@ -0,0 +1,684 @@
|
||||
#ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED
|
||||
|
||||
// local_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>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<class T> class local_shared_ptr;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
|
||||
{
|
||||
boost::detail::sp_assert_convertible< Y, E >();
|
||||
|
||||
typedef boost::detail::local_sp_deleter< boost::checked_deleter<Y> > D;
|
||||
|
||||
boost::shared_ptr<E> p2( p, D() );
|
||||
|
||||
D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
|
||||
|
||||
pd->pn_ = p2._internal_count();
|
||||
|
||||
pn = pd;
|
||||
}
|
||||
|
||||
template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[] > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
|
||||
{
|
||||
boost::detail::sp_assert_convertible< Y[], E[] >();
|
||||
|
||||
typedef boost::detail::local_sp_deleter< boost::checked_array_deleter<E> > D;
|
||||
|
||||
boost::shared_ptr<E[]> p2( p, D() );
|
||||
|
||||
D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
|
||||
|
||||
pd->pn_ = p2._internal_count();
|
||||
|
||||
pn = pd;
|
||||
}
|
||||
|
||||
template< class E, std::size_t N, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[N] > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn )
|
||||
{
|
||||
boost::detail::sp_assert_convertible< Y[N], E[N] >();
|
||||
|
||||
typedef boost::detail::local_sp_deleter< boost::checked_array_deleter<E> > D;
|
||||
|
||||
boost::shared_ptr<E[N]> p2( p, D() );
|
||||
|
||||
D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() );
|
||||
|
||||
pd->pn_ = p2._internal_count();
|
||||
|
||||
pn = pd;
|
||||
}
|
||||
|
||||
template< class E, class P, class D > inline void lsp_deleter_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, boost::detail::local_counted_base * & pn )
|
||||
{
|
||||
typedef boost::detail::local_sp_deleter<D> D2;
|
||||
|
||||
boost::shared_ptr<E> p2( p, D2( d ) );
|
||||
|
||||
D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() );
|
||||
|
||||
pd->pn_ = p2._internal_count();
|
||||
|
||||
pn = pd;
|
||||
}
|
||||
|
||||
template< class E, class P, class D, class A > inline void lsp_allocator_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, A const& a, boost::detail::local_counted_base * & pn )
|
||||
{
|
||||
typedef boost::detail::local_sp_deleter<D> D2;
|
||||
|
||||
boost::shared_ptr<E> p2( p, D2( d ), a );
|
||||
|
||||
D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() );
|
||||
|
||||
pd->pn_ = p2._internal_count();
|
||||
|
||||
pn = pd;
|
||||
}
|
||||
|
||||
struct lsp_internal_constructor_tag
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//
|
||||
// local_shared_ptr
|
||||
//
|
||||
// as shared_ptr, but local to a thread.
|
||||
// reference count manipulations are non-atomic.
|
||||
//
|
||||
|
||||
template<class T> class local_shared_ptr
|
||||
{
|
||||
private:
|
||||
|
||||
typedef local_shared_ptr this_type;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename boost::detail::sp_element<T>::type element_type;
|
||||
|
||||
private:
|
||||
|
||||
element_type * px;
|
||||
boost::detail::local_counted_base * pn;
|
||||
|
||||
template<class Y> friend class local_shared_ptr;
|
||||
|
||||
public:
|
||||
|
||||
// destructor
|
||||
|
||||
~local_shared_ptr() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
if( pn )
|
||||
{
|
||||
pn->release();
|
||||
}
|
||||
}
|
||||
|
||||
// constructors
|
||||
|
||||
BOOST_CONSTEXPR local_shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_NULLPTR )
|
||||
|
||||
BOOST_CONSTEXPR local_shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// internal constructor, used by make_shared
|
||||
BOOST_CONSTEXPR local_shared_ptr( boost::detail::lsp_internal_constructor_tag, element_type * px_, boost::detail::local_counted_base * pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ )
|
||||
{
|
||||
}
|
||||
|
||||
template<class Y>
|
||||
explicit local_shared_ptr( Y * p ): px( p ), pn( 0 )
|
||||
{
|
||||
boost::detail::lsp_pointer_construct( this, p, pn );
|
||||
}
|
||||
|
||||
template<class Y, class D> local_shared_ptr( Y * p, D d ): px( p ), pn( 0 )
|
||||
{
|
||||
boost::detail::lsp_deleter_construct( this, p, d, pn );
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_NULLPTR )
|
||||
|
||||
template<class D> local_shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( 0 )
|
||||
{
|
||||
boost::detail::lsp_deleter_construct( this, p, d, pn );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class Y, class D, class A> local_shared_ptr( Y * p, D d, A a ): px( p ), pn( 0 )
|
||||
{
|
||||
boost::detail::lsp_allocator_construct( this, p, d, a, pn );
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_NULLPTR )
|
||||
|
||||
template<class D, class A> local_shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( 0 )
|
||||
{
|
||||
boost::detail::lsp_allocator_construct( this, p, d, a, pn );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// construction from shared_ptr
|
||||
|
||||
template<class Y> local_shared_ptr( shared_ptr<Y> const & r,
|
||||
typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() )
|
||||
: px( r.get() ), pn( 0 )
|
||||
{
|
||||
boost::detail::sp_assert_convertible< Y, T >();
|
||||
|
||||
if( r.use_count() != 0 )
|
||||
{
|
||||
pn = new boost::detail::local_counted_impl( r._internal_count() );
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
template<class Y> local_shared_ptr( shared_ptr<Y> && r,
|
||||
typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() )
|
||||
: px( r.get() ), pn( 0 )
|
||||
{
|
||||
boost::detail::sp_assert_convertible< Y, T >();
|
||||
|
||||
if( r.use_count() != 0 )
|
||||
{
|
||||
pn = new boost::detail::local_counted_impl( r._internal_count() );
|
||||
r.reset();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// construction from unique_ptr
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
template< class Y, class D >
|
||||
local_shared_ptr( std::unique_ptr< Y, D > && r,
|
||||
typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() )
|
||||
: px( r.get() ), pn( 0 )
|
||||
{
|
||||
boost::detail::sp_assert_convertible< Y, T >();
|
||||
|
||||
if( px )
|
||||
{
|
||||
pn = new boost::detail::local_counted_impl( shared_ptr<T>( std::move(r) )._internal_count() );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template< class Y, class D >
|
||||
local_shared_ptr( boost::movelib::unique_ptr< Y, D > r ); // !
|
||||
// : px( r.get() ), pn( new boost::detail::local_counted_impl( shared_ptr<T>( std::move(r) ) ) )
|
||||
//{
|
||||
// boost::detail::sp_assert_convertible< Y, T >();
|
||||
//}
|
||||
|
||||
// copy constructor
|
||||
|
||||
local_shared_ptr( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
|
||||
{
|
||||
if( pn )
|
||||
{
|
||||
pn->add_ref();
|
||||
}
|
||||
}
|
||||
|
||||
// move constructor
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
local_shared_ptr( local_shared_ptr && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn )
|
||||
{
|
||||
r.px = 0;
|
||||
r.pn = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// converting copy constructor
|
||||
|
||||
template<class Y> local_shared_ptr( local_shared_ptr<Y> const & r,
|
||||
typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() ) BOOST_SP_NOEXCEPT
|
||||
: px( r.px ), pn( r.pn )
|
||||
{
|
||||
boost::detail::sp_assert_convertible< Y, T >();
|
||||
|
||||
if( pn )
|
||||
{
|
||||
pn->add_ref();
|
||||
}
|
||||
}
|
||||
|
||||
// converting move constructor
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
template<class Y> local_shared_ptr( local_shared_ptr<Y> && r,
|
||||
typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() ) BOOST_SP_NOEXCEPT
|
||||
: px( r.px ), pn( r.pn )
|
||||
{
|
||||
boost::detail::sp_assert_convertible< Y, T >();
|
||||
|
||||
r.px = 0;
|
||||
r.pn = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// aliasing
|
||||
|
||||
template<class Y>
|
||||
local_shared_ptr( local_shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
|
||||
{
|
||||
if( pn )
|
||||
{
|
||||
pn->add_ref();
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
template<class Y>
|
||||
local_shared_ptr( local_shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn )
|
||||
{
|
||||
r.px = 0;
|
||||
r.pn = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// assignment
|
||||
|
||||
local_shared_ptr & operator=( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
local_shared_ptr( r ).swap( *this );
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Y> local_shared_ptr & operator=( local_shared_ptr<Y> const & r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
local_shared_ptr( r ).swap( *this );
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
local_shared_ptr & operator=( local_shared_ptr && r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
local_shared_ptr( std::move( r ) ).swap( *this );
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class Y>
|
||||
local_shared_ptr & operator=( local_shared_ptr<Y> && r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
local_shared_ptr( std::move( r ) ).swap( *this );
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_NULLPTR )
|
||||
|
||||
local_shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
local_shared_ptr().swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
template<class Y, class D>
|
||||
local_shared_ptr & operator=( std::unique_ptr<Y, D> && r )
|
||||
{
|
||||
local_shared_ptr( std::move(r) ).swap( *this );
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class Y, class D>
|
||||
local_shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r ); // !
|
||||
|
||||
// reset
|
||||
|
||||
void reset() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
local_shared_ptr().swap( *this );
|
||||
}
|
||||
|
||||
template<class Y> void reset( Y * p ) // Y must be complete
|
||||
{
|
||||
local_shared_ptr( p ).swap( *this );
|
||||
}
|
||||
|
||||
template<class Y, class D> void reset( Y * p, D d )
|
||||
{
|
||||
local_shared_ptr( p, d ).swap( *this );
|
||||
}
|
||||
|
||||
template<class Y, class D, class A> void reset( Y * p, D d, A a )
|
||||
{
|
||||
local_shared_ptr( p, d, a ).swap( *this );
|
||||
}
|
||||
|
||||
template<class Y> void reset( local_shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
local_shared_ptr( r, p ).swap( *this );
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
template<class Y> void reset( local_shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
local_shared_ptr( std::move( r ), p ).swap( *this );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// accessors
|
||||
|
||||
typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return *px;
|
||||
}
|
||||
|
||||
typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return px;
|
||||
}
|
||||
|
||||
typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT
|
||||
{
|
||||
BOOST_ASSERT( px != 0 );
|
||||
BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
|
||||
|
||||
return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
|
||||
}
|
||||
|
||||
element_type * get() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return px;
|
||||
}
|
||||
|
||||
// implicit conversion to "bool"
|
||||
#include <boost/smart_ptr/detail/operator_bool.hpp>
|
||||
|
||||
long local_use_count() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return pn? pn->local_use_count(): 0;
|
||||
}
|
||||
|
||||
// conversions to shared_ptr, weak_ptr
|
||||
|
||||
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
|
||||
template<class Y, class E = typename boost::detail::sp_enable_if_convertible<T,Y>::type> operator shared_ptr<Y>() const BOOST_SP_NOEXCEPT
|
||||
#else
|
||||
template<class Y> operator shared_ptr<Y>() const BOOST_SP_NOEXCEPT
|
||||
#endif
|
||||
{
|
||||
boost::detail::sp_assert_convertible<T, Y>();
|
||||
|
||||
if( pn )
|
||||
{
|
||||
return shared_ptr<Y>( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return shared_ptr<Y>();
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
|
||||
template<class Y, class E = typename boost::detail::sp_enable_if_convertible<T,Y>::type> operator weak_ptr<Y>() const BOOST_SP_NOEXCEPT
|
||||
#else
|
||||
template<class Y> operator weak_ptr<Y>() const BOOST_SP_NOEXCEPT
|
||||
#endif
|
||||
{
|
||||
boost::detail::sp_assert_convertible<T, Y>();
|
||||
|
||||
if( pn )
|
||||
{
|
||||
return shared_ptr<Y>( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return weak_ptr<Y>();
|
||||
}
|
||||
}
|
||||
|
||||
// swap
|
||||
|
||||
void swap( local_shared_ptr & r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
std::swap( px, r.px );
|
||||
std::swap( pn, r.pn );
|
||||
}
|
||||
|
||||
// owner_before
|
||||
|
||||
template<class Y> bool owner_before( local_shared_ptr<Y> const & r ) const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return std::less< boost::detail::local_counted_base* >()( pn, r.pn );
|
||||
}
|
||||
};
|
||||
|
||||
template<class T, class U> inline bool operator==( local_shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=( local_shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_NULLPTR )
|
||||
|
||||
template<class T> inline bool operator==( local_shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get() == 0;
|
||||
}
|
||||
|
||||
template<class T> inline bool operator==( boost::detail::sp_nullptr_t, local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get() == 0;
|
||||
}
|
||||
|
||||
template<class T> inline bool operator!=( local_shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get() != 0;
|
||||
}
|
||||
|
||||
template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get() != 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class T, class U> inline bool operator==( local_shared_ptr<T> const & a, shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=( local_shared_ptr<T> const & a, shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator==( shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.get() == b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator!=( shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.get() != b.get();
|
||||
}
|
||||
|
||||
template<class T, class U> inline bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return a.owner_before( b );
|
||||
}
|
||||
|
||||
template<class T> inline void swap( local_shared_ptr<T> & a, local_shared_ptr<T> & b ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
a.swap( b );
|
||||
}
|
||||
|
||||
template<class T, class U> local_shared_ptr<T> static_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) static_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename local_shared_ptr<T>::element_type E;
|
||||
|
||||
E * p = static_cast< E* >( r.get() );
|
||||
return local_shared_ptr<T>( r, p );
|
||||
}
|
||||
|
||||
template<class T, class U> local_shared_ptr<T> const_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) const_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename local_shared_ptr<T>::element_type E;
|
||||
|
||||
E * p = const_cast< E* >( r.get() );
|
||||
return local_shared_ptr<T>( r, p );
|
||||
}
|
||||
|
||||
template<class T, class U> local_shared_ptr<T> dynamic_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename local_shared_ptr<T>::element_type E;
|
||||
|
||||
E * p = dynamic_cast< E* >( r.get() );
|
||||
return p? local_shared_ptr<T>( r, p ): local_shared_ptr<T>();
|
||||
}
|
||||
|
||||
template<class T, class U> local_shared_ptr<T> reinterpret_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename local_shared_ptr<T>::element_type E;
|
||||
|
||||
E * p = reinterpret_cast< E* >( r.get() );
|
||||
return local_shared_ptr<T>( r, p );
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
template<class T, class U> local_shared_ptr<T> static_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) static_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename local_shared_ptr<T>::element_type E;
|
||||
|
||||
E * p = static_cast< E* >( r.get() );
|
||||
return local_shared_ptr<T>( std::move(r), p );
|
||||
}
|
||||
|
||||
template<class T, class U> local_shared_ptr<T> const_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) const_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename local_shared_ptr<T>::element_type E;
|
||||
|
||||
E * p = const_cast< E* >( r.get() );
|
||||
return local_shared_ptr<T>( std::move(r), p );
|
||||
}
|
||||
|
||||
template<class T, class U> local_shared_ptr<T> dynamic_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename local_shared_ptr<T>::element_type E;
|
||||
|
||||
E * p = dynamic_cast< E* >( r.get() );
|
||||
return p? local_shared_ptr<T>( std::move(r), p ): local_shared_ptr<T>();
|
||||
}
|
||||
|
||||
template<class T, class U> local_shared_ptr<T> reinterpret_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
(void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
|
||||
|
||||
typedef typename local_shared_ptr<T>::element_type E;
|
||||
|
||||
E * p = reinterpret_cast< E* >( r.get() );
|
||||
return local_shared_ptr<T>( std::move(r), p );
|
||||
}
|
||||
|
||||
#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
// get_pointer() enables boost::mem_fn to recognize local_shared_ptr
|
||||
|
||||
template<class T> inline typename local_shared_ptr<T>::element_type * get_pointer( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get();
|
||||
}
|
||||
|
||||
// operator<<
|
||||
|
||||
#if !defined(BOOST_NO_IOSTREAM)
|
||||
|
||||
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 )
|
||||
{
|
||||
os << p.get();
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif // !defined(BOOST_NO_IOSTREAM)
|
||||
|
||||
// get_deleter
|
||||
|
||||
template<class D, class T> D * get_deleter( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return get_deleter<D>( shared_ptr<T>( p ) );
|
||||
}
|
||||
|
||||
// hash_value
|
||||
|
||||
template< class T > struct hash;
|
||||
|
||||
template< class T > std::size_t hash_value( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return boost::hash< typename local_shared_ptr<T>::element_type* >()( p.get() );
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED
|
17
include/boost/smart_ptr/make_local_shared.hpp
Normal file
17
include/boost/smart_ptr/make_local_shared.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED
|
||||
|
||||
// make_local_shared.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/make_local_shared_object.hpp>
|
||||
#include <boost/smart_ptr/make_local_shared_array.hpp>
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED
|
67
include/boost/smart_ptr/make_local_shared_array.hpp
Normal file
67
include/boost/smart_ptr/make_local_shared_array.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright 2017 Peter Dimov
|
||||
Copyright 2017 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_MAKE_LOCAL_SHARED_ARRAY_HPP
|
||||
#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP
|
||||
|
||||
#include <boost/smart_ptr/allocate_local_shared_array.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<class T>
|
||||
inline typename detail::lsp_if_size_array<T>::type
|
||||
make_local_shared()
|
||||
{
|
||||
return boost::allocate_local_shared<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::lsp_if_size_array<T>::type
|
||||
make_local_shared(const typename detail::sp_array_element<T>::type& value)
|
||||
{
|
||||
return boost::allocate_local_shared<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>(), value);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::lsp_if_array<T>::type
|
||||
make_local_shared(std::size_t size)
|
||||
{
|
||||
return boost::allocate_local_shared<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>(), size);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::lsp_if_array<T>::type
|
||||
make_local_shared(std::size_t size,
|
||||
const typename detail::sp_array_element<T>::type& value)
|
||||
{
|
||||
return boost::allocate_local_shared<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>(), size, value);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::lsp_if_size_array<T>::type
|
||||
make_local_shared_noinit()
|
||||
{
|
||||
return allocate_local_shared_noinit<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::lsp_if_array<T>::type
|
||||
make_local_shared_noinit(std::size_t size)
|
||||
{
|
||||
return allocate_local_shared_noinit<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>(), size);
|
||||
}
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif
|
199
include/boost/smart_ptr/make_local_shared_object.hpp
Normal file
199
include/boost/smart_ptr/make_local_shared_object.hpp
Normal file
@@ -0,0 +1,199 @@
|
||||
#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED
|
||||
|
||||
// make_local_shared_object.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/local_shared_ptr.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// lsp_if_not_array
|
||||
|
||||
template<class T> struct lsp_if_not_array
|
||||
{
|
||||
typedef boost::local_shared_ptr<T> type;
|
||||
};
|
||||
|
||||
template<class T> struct lsp_if_not_array<T[]>
|
||||
{
|
||||
};
|
||||
|
||||
template<class T, std::size_t N> struct lsp_if_not_array<T[N]>
|
||||
{
|
||||
};
|
||||
|
||||
// lsp_ms_deleter
|
||||
|
||||
template<class T, class A> class lsp_ms_deleter: public local_counted_impl_em
|
||||
{
|
||||
private:
|
||||
|
||||
typedef typename sp_aligned_storage<sizeof(T), ::boost::alignment_of<T>::value>::type storage_type;
|
||||
|
||||
storage_type storage_;
|
||||
A a_;
|
||||
bool initialized_;
|
||||
|
||||
private:
|
||||
|
||||
void destroy() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
if( initialized_ )
|
||||
{
|
||||
T * p = reinterpret_cast< T* >( storage_.data_ );
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
|
||||
|
||||
std::allocator_traits<A>::destroy( a_, p );
|
||||
|
||||
#else
|
||||
|
||||
p->~T();
|
||||
|
||||
#endif
|
||||
|
||||
initialized_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit lsp_ms_deleter( A const & a ) BOOST_SP_NOEXCEPT : a_( a ), initialized_( false )
|
||||
{
|
||||
}
|
||||
|
||||
// optimization: do not copy storage_
|
||||
lsp_ms_deleter( lsp_ms_deleter const & r ) BOOST_SP_NOEXCEPT : a_( r.a_), initialized_( false )
|
||||
{
|
||||
}
|
||||
|
||||
~lsp_ms_deleter() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void operator()( T * ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static
|
||||
{
|
||||
}
|
||||
|
||||
void * address() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return storage_.data_;
|
||||
}
|
||||
|
||||
void set_initialized() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
initialized_ = true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T, class A, class... Args> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared( A const & a, Args&&... args )
|
||||
{
|
||||
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
|
||||
|
||||
typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
|
||||
|
||||
#else
|
||||
|
||||
typedef typename A::template rebind<T>::other A2;
|
||||
|
||||
#endif
|
||||
|
||||
A2 a2( a );
|
||||
|
||||
typedef boost::detail::lsp_ms_deleter<T, A2> D;
|
||||
|
||||
boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
|
||||
|
||||
D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
|
||||
void * pv = pd->address();
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
|
||||
|
||||
std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), std::forward<Args>( args )... );
|
||||
|
||||
#else
|
||||
|
||||
::new( pv ) T( std::forward<Args>( args )... );
|
||||
|
||||
#endif
|
||||
|
||||
pd->set_initialized();
|
||||
|
||||
T * pt2 = static_cast< T* >( pv );
|
||||
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||
|
||||
pd->pn_ = pt._internal_count();
|
||||
|
||||
return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
|
||||
}
|
||||
|
||||
template<class T, class A> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared_noinit( A const & a )
|
||||
{
|
||||
#if !defined( BOOST_NO_CXX11_ALLOCATOR )
|
||||
|
||||
typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2;
|
||||
|
||||
#else
|
||||
|
||||
typedef typename A::template rebind<T>::other A2;
|
||||
|
||||
#endif
|
||||
|
||||
A2 a2( a );
|
||||
|
||||
typedef boost::detail::lsp_ms_deleter< T, std::allocator<T> > D;
|
||||
|
||||
boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 );
|
||||
|
||||
D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() );
|
||||
void * pv = pd->address();
|
||||
|
||||
::new( pv ) T;
|
||||
|
||||
pd->set_initialized();
|
||||
|
||||
T * pt2 = static_cast< T* >( pv );
|
||||
boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 );
|
||||
|
||||
pd->pn_ = pt._internal_count();
|
||||
|
||||
return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd );
|
||||
}
|
||||
|
||||
template<class T, class... Args> typename boost::detail::lsp_if_not_array<T>::type make_local_shared( Args&&... args )
|
||||
{
|
||||
return boost::allocate_local_shared<T>( std::allocator<T>(), std::forward<Args>(args)... );
|
||||
}
|
||||
|
||||
template<class T> typename boost::detail::lsp_if_not_array<T>::type make_local_shared_noinit()
|
||||
{
|
||||
return boost::allocate_shared_noinit<T>( std::allocator<T>() );
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
|
@@ -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_object.hpp>
|
||||
|
||||
|
@@ -1,158 +1,66 @@
|
||||
/*
|
||||
* 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-2017 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_MAKE_SHARED_ARRAY_HPP
|
||||
#define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
|
||||
|
||||
#include <boost/smart_ptr/detail/array_count_impl.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_if_array.hpp>
|
||||
#include <boost/smart_ptr/allocate_shared_array.hpp>
|
||||
|
||||
namespace boost {
|
||||
template<class T>
|
||||
inline typename boost::detail::sp_if_array<T>::type
|
||||
make_shared(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_allocator<T> 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(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_init(p2, n1);
|
||||
a2->set(p2);
|
||||
p1 = reinterpret_cast<T1*>(p2);
|
||||
return shared_ptr<T>(s1, p1);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename boost::detail::sp_if_size_array<T>::type
|
||||
make_shared() {
|
||||
typedef typename boost::detail::array_inner<T>::type T1;
|
||||
typedef typename boost::detail::array_base<T1>::type T2;
|
||||
typedef boost::detail::ms_allocator<T> 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(&p2);
|
||||
shared_ptr<T> s1(p1, d1, a1);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
boost::detail::ms_init(p2, N);
|
||||
a2->set(p2);
|
||||
p1 = reinterpret_cast<T1*>(p2);
|
||||
return shared_ptr<T>(s1, p1);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename boost::detail::sp_if_array<T>::type
|
||||
make_shared(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_allocator<T> 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(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_init<T2, M>(p2, n1, p3);
|
||||
a2->set(p2);
|
||||
p1 = reinterpret_cast<T1*>(p2);
|
||||
return shared_ptr<T>(s1, p1);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename boost::detail::sp_if_size_array<T>::type
|
||||
make_shared(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_allocator<T> A1;
|
||||
typedef boost::detail::ms_in_allocator_tag D1;
|
||||
enum {
|
||||
M = boost::detail::array_total<T1>::size,
|
||||
N = boost::detail::array_total<T>::size
|
||||
};
|
||||
T1* p1 = 0;
|
||||
T2* p2 = 0;
|
||||
T3* p3 = reinterpret_cast<T3*>(&value);
|
||||
D1 d1;
|
||||
A1 a1(&p2);
|
||||
shared_ptr<T> s1(p1, d1, a1);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
boost::detail::ms_init<T2, M>(p2, N, p3);
|
||||
a2->set(p2);
|
||||
p1 = reinterpret_cast<T1*>(p2);
|
||||
return shared_ptr<T>(s1, p1);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename boost::detail::sp_if_array<T>::type
|
||||
make_shared_noinit(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_allocator<T> 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(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>
|
||||
inline typename boost::detail::sp_if_size_array<T>::type
|
||||
make_shared_noinit() {
|
||||
typedef typename boost::detail::array_inner<T>::type T1;
|
||||
typedef typename boost::detail::array_base<T1>::type T2;
|
||||
typedef boost::detail::ms_allocator<T> 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(&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>
|
||||
inline typename detail::sp_if_size_array<T>::type
|
||||
make_shared()
|
||||
{
|
||||
return boost::allocate_shared<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::sp_if_size_array<T>::type
|
||||
make_shared(const typename detail::sp_array_element<T>::type& value)
|
||||
{
|
||||
return boost::allocate_shared<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>(), value);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::sp_if_array<T>::type
|
||||
make_shared(std::size_t size)
|
||||
{
|
||||
return boost::allocate_shared<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>(), size);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::sp_if_array<T>::type
|
||||
make_shared(std::size_t size,
|
||||
const typename detail::sp_array_element<T>::type& value)
|
||||
{
|
||||
return boost::allocate_shared<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>(), size, value);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::sp_if_size_array<T>::type
|
||||
make_shared_noinit()
|
||||
{
|
||||
return allocate_shared_noinit<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::sp_if_array<T>::type
|
||||
make_shared_noinit(std::size_t size)
|
||||
{
|
||||
return allocate_shared_noinit<T>(std::allocator<typename
|
||||
detail::sp_array_scalar<T>::type>(), size);
|
||||
}
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user