mirror of
https://github.com/boostorg/smart_ptr.git
synced 2025-10-04 19:51:02 +02:00
Compare commits
229 Commits
boost-1.61
...
feature/lo
Author | SHA1 | Date | |
---|---|---|---|
|
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 | ||
|
f3279d24b4 | ||
|
c87b6e8af8 | ||
|
aaded4f85c | ||
|
eb1a002e34 | ||
|
3304a56101 | ||
|
181f38682f | ||
|
5b1a8412c3 | ||
|
e52905cf3c | ||
|
b7f99ceba6 | ||
|
a7ade6f062 | ||
|
097d2e9bf9 | ||
|
d44a78d671 | ||
|
582eb63cb3 | ||
|
181b449a57 | ||
|
da8de3e95b | ||
|
6c27833099 | ||
|
522f6c1869 | ||
|
cd8de9d4a6 | ||
|
05d5a4e9a0 | ||
|
970a179ac2 | ||
|
fd543d3292 | ||
|
334654de06 |
537
.travis.yml
Normal file
537
.travis.yml
Normal file
@@ -0,0 +1,537 @@
|
||||
# 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://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
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=c++03
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.7
|
||||
env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.7
|
||||
env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=c++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=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.8
|
||||
env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=c++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=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.9
|
||||
env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=c++11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-5
|
||||
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-5
|
||||
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-5
|
||||
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-5
|
||||
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-6
|
||||
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-6
|
||||
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-6
|
||||
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-6
|
||||
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++17
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++03
|
||||
|
||||
- os: linux
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++11
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.5
|
||||
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.5
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.5
|
||||
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=c++11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.5
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.5
|
||||
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=c++14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.5
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.5
|
||||
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=c++1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.5
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.5
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.6
|
||||
env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.6
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.6
|
||||
env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=c++11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.6
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.6
|
||||
env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=c++14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.6
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.6
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.6
|
||||
env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=c++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=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.7
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.7
|
||||
env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=c++11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.7
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.7
|
||||
env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=c++14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.7
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.7
|
||||
env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=c++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=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.8
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.8
|
||||
env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.8
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.8
|
||||
env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.8
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.8
|
||||
env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.8
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.9
|
||||
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.9
|
||||
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.9
|
||||
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.9
|
||||
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-4.0
|
||||
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++03
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-4.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-4.0
|
||||
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-4.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-4.0
|
||||
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++14
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-4.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-4.0
|
||||
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++1z
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-4.0
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-4.0
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++03
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++11
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++1z
|
||||
|
||||
install:
|
||||
- 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/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/static_assert
|
||||
- git submodule init libs/throw_exception
|
||||
- git submodule init libs/type_traits
|
||||
- git submodule init tools/build
|
||||
- git submodule update
|
||||
- cp -r $TRAVIS_BUILD_DIR/* libs/smart_ptr
|
||||
- ./bootstrap.sh
|
||||
- ./b2 headers
|
||||
|
||||
script:
|
||||
- |-
|
||||
echo "using $TOOLSET : : $COMPILER : <cxxflags>-std=$CXXSTD ;" > ~/user-config.jam
|
||||
- ./b2 libs/smart_ptr/test toolset=$TOOLSET
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: always
|
6
README.md
Normal file
6
README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Boost.SmartPtr
|
||||
|
||||
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)
|
59
appveyor.yml
Normal file
59
appveyor.yml
Normal file
@@ -0,0 +1,59 @@
|
||||
# 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://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
version: 1.0.{build}-{branch}
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /feature\/.*/
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
TOOLSET: msvc-9.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
TOOLSET: msvc-10.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
TOOLSET: msvc-11.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
|
||||
TOOLSET: msvc-12.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
TOOLSET: msvc-14.0
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLSET: msvc-14.1
|
||||
|
||||
install:
|
||||
- set BOOST_BRANCH=develop
|
||||
- if "%APPVEYOR_REPO_BRANCH%" == "master" set BOOST_BRANCH=master
|
||||
- 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/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/static_assert
|
||||
- git submodule init libs/throw_exception
|
||||
- git submodule init libs/type_traits
|
||||
- git submodule init tools/build
|
||||
- git submodule update
|
||||
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\smart_ptr
|
||||
- bootstrap
|
||||
- b2 headers
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- b2 libs/smart_ptr/test toolset=%TOOLSET%
|
@@ -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 ;
|
50
doc/asciidoctor.jam
Normal file
50
doc/asciidoctor.jam
Normal file
@@ -0,0 +1,50 @@
|
||||
# Copyright 2017 Peter Dimov
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
import type ;
|
||||
import scanner ;
|
||||
import generators ;
|
||||
import boostbook ;
|
||||
|
||||
# File type
|
||||
|
||||
type.register ASCIIDOC : asciidoc adoc ;
|
||||
|
||||
# Define dependency scanner
|
||||
|
||||
class asciidoc-scanner : common-scanner
|
||||
{
|
||||
rule pattern ( )
|
||||
{
|
||||
return "include::([^[]+)\\[" ;
|
||||
}
|
||||
}
|
||||
|
||||
scanner.register asciidoc-scanner : include ;
|
||||
type.set-scanner ASCIIDOC : asciidoc-scanner ;
|
||||
|
||||
# Define generators
|
||||
|
||||
generators.register-standard asciidoctor.asciidoc-to-html : ASCIIDOC : HTML ;
|
||||
generators.register-standard asciidoctor.asciidoc-to-pdf : ASCIIDOC : PDF ;
|
||||
# generators.register-standard asciidoctor.asciidoc-to-docbook : ASCIIDOC : DOCBOOK ;
|
||||
|
||||
# Define actions
|
||||
|
||||
actions asciidoc-to-html
|
||||
{
|
||||
asciidoctor -b html -o $(1) $(2)
|
||||
}
|
||||
|
||||
actions asciidoc-to-pdf
|
||||
{
|
||||
asciidoctor -r asciidoctor-pdf -b pdf -o $(1) $(2)
|
||||
}
|
||||
|
||||
actions asciidoc-to-docbook
|
||||
{
|
||||
asciidoctor -b docbook -o $(1) $(2)
|
||||
}
|
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>
|
74
doc/smart_ptr.adoc
Normal file
74
doc/smart_ptr.adoc
Normal file
@@ -0,0 +1,74 @@
|
||||
////
|
||||
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/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`.
|
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:: `if(r.get() != 0) intrusive_ptr_add_ref(r.get());`.
|
||||
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.
|
||||
|
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_unqiue.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>
|
BIN
gccspeed.gif
BIN
gccspeed.gif
Binary file not shown.
Before Width: | Height: | Size: 6.4 KiB |
@@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
183
include/boost/smart_ptr/atomic_shared_ptr.hpp
Normal file
183
include/boost/smart_ptr/atomic_shared_ptr.hpp
Normal file
@@ -0,0 +1,183 @@
|
||||
#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( int = 0 ) 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, int = 0 ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
boost::detail::spinlock::scoped_lock lock( l_ );
|
||||
p_.swap( r );
|
||||
}
|
||||
|
||||
shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) 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
|
||||
}
|
||||
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, w );
|
||||
}
|
||||
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, w );
|
||||
}
|
||||
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, w );
|
||||
}
|
||||
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, w );
|
||||
}
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
|
||||
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, std::move( w ) );
|
||||
}
|
||||
|
||||
bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, std::move( w ) );
|
||||
}
|
||||
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return compare_exchange( v, std::move( w ) );
|
||||
}
|
||||
|
||||
bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) 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
|
||||
|
147
include/boost/smart_ptr/detail/local_counted_base.hpp
Normal file
147
include/boost/smart_ptr/detail/local_counted_base.hpp
Normal file
@@ -0,0 +1,147 @@
|
||||
#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>
|
||||
#include <climits>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class 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_ = UINT_MAX };
|
||||
|
||||
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( __has_builtin )
|
||||
# if __has_builtin( __builtin_assume )
|
||||
|
||||
__builtin_assume( local_use_count_ >= 1 );
|
||||
|
||||
# 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 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 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,13 +53,13 @@ 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
|
||||
|
||||
@@ -75,15 +81,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 +108,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,7 @@ 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
|
||||
@@ -249,18 +249,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 +266,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 +306,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 +323,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 +496,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 +522,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 )
|
||||
|
@@ -104,6 +104,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()
|
||||
|
@@ -96,6 +96,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()
|
||||
|
@@ -58,6 +58,11 @@ inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t *
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
# pragma clang diagnostic ignored "-Wweak-vtables"
|
||||
#endif
|
||||
|
||||
class sp_counted_base
|
||||
{
|
||||
private:
|
||||
@@ -93,6 +98,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 +139,10 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
@@ -124,6 +124,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()
|
||||
|
@@ -112,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()
|
||||
|
@@ -111,6 +111,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()
|
||||
|
@@ -135,6 +135,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()
|
||||
|
@@ -135,6 +135,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()
|
||||
|
@@ -120,6 +120,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()
|
||||
|
@@ -127,6 +127,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()
|
||||
|
@@ -59,6 +59,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()
|
||||
|
@@ -71,6 +71,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()
|
||||
|
@@ -115,6 +115,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()
|
||||
|
@@ -62,6 +62,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()
|
||||
|
@@ -84,6 +84,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()
|
||||
|
@@ -90,6 +90,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()
|
||||
|
@@ -109,6 +109,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()
|
||||
|
@@ -104,6 +104,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()
|
||||
|
@@ -67,6 +67,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,6 +51,19 @@ void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn );
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// 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 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;
|
||||
@@ -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 );
|
||||
@@ -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
|
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>
|
||||
|
||||
|
@@ -104,7 +104,7 @@ private:
|
||||
}
|
||||
|
||||
// Note: invoked automatically by shared_ptr; do not call
|
||||
template<class X, class Y> void _internal_accept_owner( shared_ptr<X> * ppx, Y * py ) const
|
||||
template<class X, class Y> void _internal_accept_owner( shared_ptr<X> * ppx, Y * ) const
|
||||
{
|
||||
BOOST_ASSERT( ppx != 0 );
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
intrusive_ptr() BOOST_NOEXCEPT : px( 0 )
|
||||
BOOST_CONSTEXPR intrusive_ptr() BOOST_SP_NOEXCEPT : px( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -111,17 +112,41 @@ 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;
|
||||
}
|
||||
|
||||
template<class U> friend class intrusive_ptr;
|
||||
|
||||
template<class U>
|
||||
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
|
||||
|
||||
intrusive_ptr(intrusive_ptr<U> && rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty())
|
||||
|
||||
#else
|
||||
|
||||
intrusive_ptr(intrusive_ptr<U> && rhs)
|
||||
|
||||
#endif
|
||||
: px( rhs.px )
|
||||
{
|
||||
rhs.px = 0;
|
||||
}
|
||||
|
||||
template<class U>
|
||||
intrusive_ptr & operator=(intrusive_ptr<U> && rhs) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
intrusive_ptr & operator=(intrusive_ptr const & rhs)
|
||||
@@ -136,7 +161,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset() BOOST_NOEXCEPT
|
||||
void reset()
|
||||
{
|
||||
this_type().swap( *this );
|
||||
}
|
||||
@@ -151,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;
|
||||
@@ -178,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;
|
||||
@@ -190,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();
|
||||
}
|
||||
@@ -224,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();
|
||||
}
|
||||
@@ -233,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();
|
||||
}
|
||||
@@ -326,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,19 +72,19 @@ 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 --counter;
|
||||
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, T * 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
|
63
include/boost/smart_ptr/make_local_shared_array.hpp
Normal file
63
include/boost/smart_ptr/make_local_shared_array.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP_INCLUDED
|
||||
|
||||
// make_local_shared_array.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/config.hpp>
|
||||
#include <boost/smart_ptr/make_shared.hpp>
|
||||
#include <utility>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class T> struct lsp_if_array
|
||||
{
|
||||
};
|
||||
|
||||
template<class T> struct lsp_if_array<T[]>
|
||||
{
|
||||
typedef boost::local_shared_ptr<T[]> type;
|
||||
};
|
||||
|
||||
template<class T, std::size_t N> struct lsp_if_array<T[N]>
|
||||
{
|
||||
typedef boost::local_shared_ptr<T[N]> type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<class T, class... Args> typename boost::detail::lsp_if_array<T>::type make_local_shared( Args&&... args )
|
||||
{
|
||||
return boost::make_shared<T>( std::forward<Args>(args)... );
|
||||
}
|
||||
|
||||
template<class T, class... Args> typename boost::detail::lsp_if_array<T>::type make_local_shared_noinit( Args&&... args )
|
||||
{
|
||||
return boost::make_shared_noinit<T>( std::forward<Args>(args)... );
|
||||
}
|
||||
|
||||
template<class T, class A, class... Args> typename boost::detail::lsp_if_array<T>::type allocate_local_shared( A const & a, Args&&... args )
|
||||
{
|
||||
return boost::allocate_shared<T>( a, std::forward<Args>(args)... );
|
||||
}
|
||||
|
||||
template<class T, class A, class... Args> typename boost::detail::lsp_if_array<T>::type allocate_local_shared_noinit( A const & a, Args&&... args )
|
||||
{
|
||||
return boost::allocate_shared_noinit<T>( a, std::forward<Args>(args)... );
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
|
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, 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();
|
||||
|
||||
::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
@@ -1,10 +1,9 @@
|
||||
/*
|
||||
(c) 2014-2015 Glen Joseph Fernandes
|
||||
<glenjofe -at- gmail.com>
|
||||
Copyright 2012-2015 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_SMART_PTR_MAKE_UNIQUE_HPP
|
||||
#define BOOST_SMART_PTR_MAKE_UNIQUE_HPP
|
||||
@@ -15,6 +14,7 @@ http://boost.org/LICENSE_1_0.txt
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
template<class T>
|
||||
struct up_if_object {
|
||||
typedef std::unique_ptr<T> type;
|
||||
@@ -56,10 +56,12 @@ template<class T>
|
||||
struct up_element<T[]> {
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
} /* detail */
|
||||
|
||||
template<class T>
|
||||
inline typename detail::up_if_object<T>::type make_unique()
|
||||
inline typename detail::up_if_object<T>::type
|
||||
make_unique()
|
||||
{
|
||||
return std::unique_ptr<T>(new T());
|
||||
}
|
||||
@@ -67,7 +69,7 @@ inline typename detail::up_if_object<T>::type make_unique()
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<class T, class... Args>
|
||||
inline typename detail::up_if_object<T>::type
|
||||
make_unique(Args&&... args)
|
||||
make_unique(Args&&... args)
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
@@ -75,31 +77,34 @@ inline typename detail::up_if_object<T>::type
|
||||
|
||||
template<class T>
|
||||
inline typename detail::up_if_object<T>::type
|
||||
make_unique(typename detail::up_remove_reference<T>::type&& value)
|
||||
make_unique(typename detail::up_remove_reference<T>::type&& value)
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::move(value)));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::up_if_object<T>::type make_unique_noinit()
|
||||
inline typename detail::up_if_object<T>::type
|
||||
make_unique_noinit()
|
||||
{
|
||||
return std::unique_ptr<T>(new T);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::up_if_array<T>::type make_unique(std::size_t n)
|
||||
inline typename detail::up_if_array<T>::type
|
||||
make_unique(std::size_t size)
|
||||
{
|
||||
return std::unique_ptr<T>(new
|
||||
typename detail::up_element<T>::type[n]());
|
||||
return std::unique_ptr<T>(new typename
|
||||
detail::up_element<T>::type[size]());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename detail::up_if_array<T>::type
|
||||
make_unique_noinit(std::size_t n)
|
||||
make_unique_noinit(std::size_t size)
|
||||
{
|
||||
return std::unique_ptr<T>(new
|
||||
typename detail::up_element<T>::type[n]);
|
||||
return std::unique_ptr<T>(new typename
|
||||
detail::up_element<T>::type[size]);
|
||||
}
|
||||
|
||||
} /* boost */
|
||||
|
||||
#endif
|
||||
|
@@ -5,52 +5,29 @@
|
||||
// owner_less.hpp
|
||||
//
|
||||
// Copyright (c) 2008 Frank Mori Hess
|
||||
// Copyright (c) 2016 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/smart_ptr.htm for documentation.
|
||||
// See http://www.boost.org/libs/smart_ptr/ for documentation.
|
||||
//
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
template<typename T> class shared_ptr;
|
||||
template<typename T> class weak_ptr;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename T, typename U>
|
||||
struct generic_owner_less : public std::binary_function<T, T, bool>
|
||||
template<class T = void> struct owner_less
|
||||
{
|
||||
typedef bool result_type;
|
||||
typedef T first_argument_type;
|
||||
typedef T second_argument_type;
|
||||
|
||||
template<class U, class V> bool operator()( U const & u, V const & v ) const
|
||||
{
|
||||
bool operator()(const T &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs.owner_before(rhs);
|
||||
}
|
||||
bool operator()(const T &lhs, const U &rhs) const
|
||||
{
|
||||
return lhs.owner_before(rhs);
|
||||
}
|
||||
bool operator()(const U &lhs, const T &rhs) const
|
||||
{
|
||||
return lhs.owner_before(rhs);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
template<typename T> struct owner_less;
|
||||
|
||||
template<typename T>
|
||||
struct owner_less<shared_ptr<T> >:
|
||||
public detail::generic_owner_less<shared_ptr<T>, weak_ptr<T> >
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
struct owner_less<weak_ptr<T> >:
|
||||
public detail::generic_owner_less<weak_ptr<T>, shared_ptr<T> >
|
||||
{};
|
||||
return u.owner_before( v );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
@@ -8,13 +8,13 @@
|
||||
// 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/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
|
||||
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
@@ -54,14 +54,14 @@ public:
|
||||
|
||||
typedef T element_type;
|
||||
|
||||
explicit scoped_array( T * p = 0 ) BOOST_NOEXCEPT : px( p )
|
||||
explicit scoped_array( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p )
|
||||
{
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
boost::sp_array_constructor_hook( px );
|
||||
#endif
|
||||
}
|
||||
|
||||
~scoped_array() // never throws
|
||||
~scoped_array() BOOST_SP_NOEXCEPT
|
||||
{
|
||||
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
|
||||
boost::sp_array_destructor_hook( px );
|
||||
@@ -69,20 +69,20 @@ public:
|
||||
boost::checked_array_delete( px );
|
||||
}
|
||||
|
||||
void reset(T * p = 0) // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
|
||||
void reset(T * p = 0) BOOST_SP_NOEXCEPT_WITH_ASSERT
|
||||
{
|
||||
BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
|
||||
this_type(p).swap(*this);
|
||||
}
|
||||
|
||||
T & operator[](std::ptrdiff_t i) const // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
|
||||
T & operator[](std::ptrdiff_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT
|
||||
{
|
||||
BOOST_ASSERT( px != 0 );
|
||||
BOOST_ASSERT( i >= 0 );
|
||||
return px[i];
|
||||
}
|
||||
|
||||
T * get() const BOOST_NOEXCEPT
|
||||
T * get() const BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return px;
|
||||
}
|
||||
@@ -90,7 +90,7 @@ public:
|
||||
// implicit conversion to "bool"
|
||||
#include <boost/smart_ptr/detail/operator_bool.hpp>
|
||||
|
||||
void swap(scoped_array & b) BOOST_NOEXCEPT
|
||||
void swap(scoped_array & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
T * tmp = b.px;
|
||||
b.px = px;
|
||||
@@ -100,29 +100,29 @@ public:
|
||||
|
||||
#if !defined( BOOST_NO_CXX11_NULLPTR )
|
||||
|
||||
template<class T> inline bool operator==( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
|
||||
template<class T> inline bool operator==( scoped_array<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, scoped_array<T> const & p ) BOOST_NOEXCEPT
|
||||
template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get() == 0;
|
||||
}
|
||||
|
||||
template<class T> inline bool operator!=( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
|
||||
template<class T> inline bool operator!=( scoped_array<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, scoped_array<T> const & p ) BOOST_NOEXCEPT
|
||||
template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
return p.get() != 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) BOOST_NOEXCEPT
|
||||
template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) BOOST_SP_NOEXCEPT
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user