Compare commits

...

52 Commits

Author SHA1 Message Date
Peter Dimov
8f40bff2f6 Remove cxxstd=2a from clang-8 2021-10-29 00:48:48 +03:00
Peter Dimov
1ef8f4e72d Remove 16.04 from ci.yml 2021-10-28 23:31:51 +03:00
Peter Dimov
f651a49d96 Enable syntax hightlighting 2021-10-28 23:16:09 +03:00
Peter Dimov
598314b8e1 Add msvc-14.3 to ci.yml 2021-10-28 23:15:44 +03:00
Peter Dimov
72221d1da0 Update ci.yml 2021-06-08 18:59:28 +03:00
Peter Dimov
2cbeb5b185 Update ci.yml 2021-06-08 18:32:47 +03:00
Peter Dimov
67e657c228 Build CMake tests in .travis.yml 2021-06-08 08:18:47 +03:00
Peter Dimov
eba3cf92e7 Disable failing tests on 4.4 in addition to 4.4.7 2021-06-08 05:58:06 +03:00
Peter Dimov
8340a13539 Merge branch 'feature/move-up-deleter' into feature/move-only-deleter 2021-05-11 18:03:35 +03:00
Peter Dimov
098d0f4ce3 Disable sp_unique_ptr_test2 on msvc-10.0 2021-05-11 15:54:21 +03:00
Peter Dimov
fec5fb97c8 Enable move-only deleters in the nullptr_t constructors 2021-05-11 02:15:27 +03:00
Peter Dimov
b52d7548b3 Enable move-only deleters in the allocator constructor 2021-05-11 02:05:28 +03:00
Peter Dimov
594c7485a5 Enable move-only deleters 2021-05-11 01:59:01 +03:00
Peter Dimov
d751041fb9 Add more test cases to sp_unique_ptr_test2 2021-05-11 01:33:48 +03:00
Peter Dimov
d41546ddce Move the unique_ptr deleter instead of copying it 2021-05-11 01:20:02 +03:00
Peter Dimov
f3424e74e8 Update .github/workflows 2021-04-19 18:53:52 +03:00
Peter Dimov
0eee7efd54 Update .github/workflows 2021-04-19 18:18:38 +03:00
Peter Dimov
dc2a127369 Update .travis.yml 2021-01-26 12:53:36 +02:00
Edward Diener
42575a0e51 Add "cxxstd" json field 2021-01-21 12:04:23 -05:00
Peter Dimov
64b2eac868 Add .github/workflows 2021-01-20 00:41:39 +02:00
Peter Dimov
856ed108e8 Update maintainer e-mail 2020-12-12 01:05:17 +02:00
Peter Dimov
678a544d27 Add cxxstd=latest to msvc-14.2 2020-11-14 21:42:09 +02:00
Peter Dimov
f1b06df6f4 Use address-model=32 for msvc-9.0,10.0,11.0 2020-11-14 21:37:15 +02:00
Peter Dimov
620620df3d Merge branch 'develop' 2020-06-19 19:17:05 +03:00
Peter Dimov
0bd61c1089 Remove boost_install call from CMakeLists.txt 2020-06-17 19:36:01 +03:00
Peter Dimov
d1295a9974 Remove boost_install call from CMakeLists.txt 2020-06-11 17:19:17 +03:00
Peter Dimov
6e8c15c02f Fix typo, trailing whitespace 2020-06-10 21:59:48 +03:00
Peter Dimov
7c0dcd338a Refactor yield_k.hpp 2020-06-10 18:58:08 +03:00
Peter Dimov
8d79ceaf8a Revert using a relaxed load before test_and_set; not necessary, and slower, with a proper yielding strategy as opposed to just pause-spinning 2020-06-10 18:20:33 +03:00
Peter Dimov
d35cf29b99 Revert "Use a relaxed load before XCHG to not lock cache line on contention (AMD spinlock recommendation per <https://probablydance.com/2019/12/30/measuring-mutexes-spinlocks-and-how-bad-the-linux-scheduler-really-is/>)"
This reverts commit 8afe162910.
2020-06-10 18:18:35 +03:00
Peter Dimov
72ca834ae8 Change yield_k to not use sp_thread_yield; using sp_thread_sleep is always strictly superior, at least on Windows 2020-06-07 21:24:21 +03:00
Peter Dimov
8afe162910 Use a relaxed load before XCHG to not lock cache line on contention (AMD spinlock recommendation per <https://probablydance.com/2019/12/30/measuring-mutexes-spinlocks-and-how-bad-the-linux-scheduler-really-is/>) 2020-06-07 21:07:35 +03:00
Peter Dimov
5d31c1c443 Refactor yield_k.hpp 2020-06-07 20:40:41 +03:00
Peter Dimov
3db4ad9a15 Use a relaxed load before test_and_set to not lock cache line on contention (AMD spinlock recommendation per <https://probablydance.com/2019/12/30/measuring-mutexes-spinlocks-and-how-bad-the-linux-scheduler-really-is/>) 2020-06-07 17:59:55 +03:00
Peter Dimov
d0655ab145 Add atomic_count_gcc_atomic.hpp 2020-06-07 06:29:14 +03:00
Peter Dimov
7c01e640f7 Use int_least32_t in atomic_count_sync; prefer it to atomic_count_gcc_x86; mark latter obsolete 2020-06-07 06:05:17 +03:00
Peter Dimov
00db1e02c6 Add spinlock_gcc_atomic.hpp 2020-06-07 05:00:03 +03:00
Peter Dimov
914b93430a Change spinlock_sync.hpp to use a single byte 2020-06-07 04:10:49 +03:00
Peter Dimov
15ffd7852b Remove Clang C11 implementation; no longer used 2020-06-07 02:05:55 +03:00
Peter Dimov
c66c4f5ed1 Mark platform-specific implementations as obsolete 2020-06-07 02:04:42 +03:00
Peter Dimov
7e9d8c39a3 Add sp_has_gcc_intrinsics.hpp, sp_counted_base_gcc_atomic.hpp 2020-06-06 20:43:08 +03:00
Peter Dimov
a0d08b17e0 Fix include guards 2020-06-06 17:13:56 +03:00
Peter Dimov
108a86cdbd Rename sp_has_sync.hpp to sp_has_sync_intrinsics.hpp 2020-06-06 17:11:28 +03:00
Peter Dimov
d08bdc86e5 Remove unused files 2020-06-06 16:59:36 +03:00
Peter Dimov
f8dcf5f6f4 Use BOOST_SMT_PAUSE starting from the first iteration 2020-06-06 16:54:57 +03:00
Peter Dimov
d38f64ded9 Update documentation 2020-06-06 00:35:12 +03:00
Peter Dimov
b66fe51566 Avoid g++ 4.4 conflict between hash() and boost::hash 2020-06-06 00:15:58 +03:00
Peter Dimov
1b5568d585 Add sp_unordered_test 2020-06-05 18:54:44 +03:00
Peter Dimov
fad0c20263 Add owner_hash 2020-06-05 18:45:00 +03:00
Peter Dimov
1c61e54b13 Update documentation 2020-06-05 18:12:59 +03:00
Peter Dimov
a0fc1e6daa Add wp_unordered_test 2020-06-04 20:52:17 +03:00
Peter Dimov
5dd84ea389 Add .owner_hash_value to shared/weak_ptr, hash_value, std::hash/equal_to specializations for weak_ptr 2020-06-04 20:40:57 +03:00
54 changed files with 2001 additions and 966 deletions

198
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,198 @@
name: CI
on:
pull_request:
push:
branches:
- master
- develop
- feature/**
env:
UBSAN_OPTIONS: print_stacktrace=1
jobs:
posix:
strategy:
fail-fast: false
matrix:
include:
- toolset: gcc-4.8
cxxstd: "03,11"
os: ubuntu-18.04
install: g++-4.8
- toolset: gcc-5
cxxstd: "03,11,14,1z"
os: ubuntu-18.04
install: g++-5
- toolset: gcc-6
cxxstd: "03,11,14,1z"
os: ubuntu-18.04
install: g++-6
- toolset: gcc-7
cxxstd: "03,11,14,17"
os: ubuntu-18.04
- toolset: gcc-8
cxxstd: "03,11,14,17,2a"
os: ubuntu-18.04
install: g++-8
- toolset: gcc-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: g++-10
- toolset: gcc-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: g++-11
- toolset: clang
compiler: clang++-3.9
cxxstd: "03,11,14"
os: ubuntu-18.04
install: clang-3.9
- toolset: clang
compiler: clang++-4.0
cxxstd: "03,11,14"
os: ubuntu-18.04
install: clang-4.0
- toolset: clang
compiler: clang++-5.0
cxxstd: "03,11,14,1z"
os: ubuntu-18.04
install: clang-5.0
- toolset: clang
compiler: clang++-6.0
cxxstd: "03,11,14,17"
os: ubuntu-18.04
install: clang-6.0
- toolset: clang
compiler: clang++-7
cxxstd: "03,11,14,17"
os: ubuntu-18.04
install: clang-7
- toolset: clang
compiler: clang++-8
cxxstd: "03,11,14,17"
os: ubuntu-20.04
install: clang-8
- toolset: clang
compiler: clang++-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-9
- toolset: clang
compiler: clang++-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-10
- toolset: clang
compiler: clang++-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-11
- toolset: clang
compiler: clang++-12
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-12
- toolset: clang
cxxstd: "03,11,14,17,2a"
os: macos-10.15
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Install packages
if: matrix.install
run: sudo apt install ${{matrix.install}}
- name: Setup Boost
run: |
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
LIBRARY=${GITHUB_REPOSITORY#*/}
echo LIBRARY: $LIBRARY
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
echo GITHUB_REF: $GITHUB_REF
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
REF=${REF#refs/heads/}
echo REF: $REF
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
echo BOOST_BRANCH: $BOOST_BRANCH
cd ..
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
./bootstrap.sh
./b2 -d0 headers
- name: Create user-config.jam
if: matrix.compiler
run: |
echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam
- name: Run tests
run: |
cd ../boost-root
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release
windows:
strategy:
fail-fast: false
matrix:
include:
- toolset: msvc-14.1
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2016
- toolset: msvc-14.2
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.3
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2022
- toolset: gcc
cxxstd: "03,11,14,17,2a"
addrmd: 64
os: windows-2019
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- name: Setup Boost
shell: cmd
run: |
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
echo LIBRARY: %LIBRARY%
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
echo GITHUB_REF: %GITHUB_REF%
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
set BOOST_BRANCH=develop
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
echo BOOST_BRANCH: %BOOST_BRANCH%
cd ..
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY%
cmd /c bootstrap
b2 -d0 headers
- name: Run tests
shell: cmd
run: |
cd ../boost-root
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release

View File

@@ -22,28 +22,48 @@ matrix:
- env: BOGUS_JOB=true
include:
- os: linux
dist: trusty
compiler: g++
env: TOOLSET=gcc CXXSTD=03,11
- os: linux
dist: xenial
compiler: g++
env: TOOLSET=gcc CXXSTD=03,11,14
- os: linux
dist: bionic
compiler: g++
env: TOOLSET=gcc CXXSTD=03,11,14,17
- os: linux
dist: focal
compiler: g++
env: TOOLSET=gcc CXXSTD=03,11,14,17
- os: linux
arch: arm64
compiler: g++
env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11,14
env: TOOLSET=gcc CXXSTD=03,11,14
- os: linux
arch: ppc64le
compiler: g++
env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11,14
env: TOOLSET=gcc CXXSTD=03,11,14
- os: linux
arch: s390x
compiler: g++
env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11,14
env: TOOLSET=gcc CXXSTD=03,11,14
- os: freebsd
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,17,2a
env: TOOLSET=clang CXXSTD=03,11,14,17,2a
- os: linux
compiler: g++-4.4
env: TOOLSET=gcc COMPILER=g++-4.4 CXXSTD=98,0x
env: TOOLSET=gcc CXXSTD=98,0x
addons:
apt:
packages:
@@ -53,7 +73,7 @@ matrix:
- os: linux
compiler: g++-4.6
env: TOOLSET=gcc COMPILER=g++-4.6 CXXSTD=03,0x
env: TOOLSET=gcc CXXSTD=03,0x
addons:
apt:
packages:
@@ -61,109 +81,10 @@ matrix:
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-4.7
env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=03,11
addons:
apt:
packages:
- g++-4.7
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-4.8
env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=03,11
addons:
apt:
packages:
- g++-4.8
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-4.9
env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=03,11
addons:
apt:
packages:
- g++-4.9
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-5
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- g++-5
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-6
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- g++-6
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-7
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-8
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=03,11,14
addons:
apt:
packages:
- g++-8
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-8
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=17,2a
addons:
apt:
packages:
- g++-8
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-9
env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=03,11,14
addons:
apt:
packages:
- g++-9
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-9
env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=17,2a
addons:
apt:
packages:
- g++-9
sources:
- ubuntu-toolchain-r-test
- os: linux
dist: bionic
compiler: g++-10
env: TOOLSET=gcc COMPILER=g++-10 CXXSTD=03,11,14
env: UBSAN=1 TOOLSET=gcc CXXSTD=03,11,14 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
addons:
apt:
packages:
@@ -174,7 +95,7 @@ matrix:
- os: linux
dist: bionic
compiler: g++-10
env: TOOLSET=gcc COMPILER=g++-10 CXXSTD=17,2a
env: UBSAN=1 TOOLSET=gcc CXXSTD=17,2a UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
addons:
apt:
packages:
@@ -182,20 +103,10 @@ matrix:
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-7
env: UBSAN=1 TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
dist: trusty
compiler: /usr/bin/clang++
env: TOOLSET=clang COMPILER=/usr/bin/clang++ CXXSTD=03,11
env: TOOLSET=clang COMMENT=clang-3.3 CXXSTD=03,11
addons:
apt:
packages:
@@ -204,160 +115,24 @@ matrix:
- os: linux
dist: trusty
compiler: /usr/bin/clang++
env: TOOLSET=clang COMPILER=/usr/bin/clang++ CXXSTD=03,11
env: TOOLSET=clang COMMENT=clang-3.4 CXXSTD=03,11
addons:
apt:
packages:
- clang-3.4
- os: linux
compiler: clang++-3.5
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=03,11
compiler: clang++-11
env: UBSAN=1 TOOLSET=clang CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
- clang-3.5
- clang-11
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: clang++-3.6
env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.6
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: clang++-3.7
env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.7
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: clang++-3.8
env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.8
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: clang++-3.9
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-3.9
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: clang++-4.0
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-4.0
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: clang++-5.0
env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z
addons:
apt:
packages:
- clang-5.0
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: clang++-6.0
env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-6.0
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: clang++-7
env: TOOLSET=clang COMPILER=clang++-7 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-7
- os: linux
compiler: clang++-8
env: TOOLSET=clang COMPILER=clang++-8 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-8
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
- os: linux
dist: xenial
compiler: clang++-9
env: TOOLSET=clang COMPILER=clang++-9 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-9
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-11 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
dist: xenial
compiler: clang++-10
env: TOOLSET=clang COMPILER=clang++-10 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-10
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-10 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
compiler: clang++-8
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-8 CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
- clang-8
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
- os: linux
dist: trusty
compiler: clang++-libc++
env: TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z
addons:
apt:
packages:
- libc++-dev
- os: linux
dist: trusty
compiler: clang++-libc++
@@ -367,9 +142,14 @@ matrix:
packages:
- libc++-dev
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
- os: linux
dist: bionic
compiler: clang++-libc++
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
- libc++-dev
- os: osx
compiler: clang++
@@ -380,6 +160,7 @@ matrix:
script:
- mkdir __build__ && cd __build__
- cmake -DBOOST_ENABLE_CMAKE=1 -DBoost_VERBOSE=1 -DBOOST_INCLUDE_LIBRARIES=smart_ptr -DBUILD_TESTING=ON ..
- cmake --build . --target tests -- -k
- ctest --output-on-failure -R boost_smart_ptr
- os: linux
@@ -394,6 +175,7 @@ matrix:
- os: linux
env: CMAKE_INSTALL_TEST=1
script:
- pip install --user cmake
- mkdir __build__ && cd __build__
- cmake -DBOOST_ENABLE_CMAKE=1 -DBoost_VERBOSE=1 -DBOOST_INCLUDE_LIBRARIES=smart_ptr -DBUILD_TESTING=OFF -DCMAKE_INSTALL_PREFIX=~/.local ..
- cmake --build . --target install
@@ -433,7 +215,7 @@ install:
script:
- |-
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
echo "using $TOOLSET : : $TRAVIS_COMPILER ;" > ~/user-config.jam
- ./b2 -j3 libs/smart_ptr/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
notifications:

View File

@@ -22,13 +22,6 @@ target_link_libraries(boost_smart_ptr
Boost::type_traits
)
if(BOOST_SUPERPROJECT_VERSION)
include(BoostInstall)
boost_install(TARGETS boost_smart_ptr HEADER_DIRECTORY include/)
endif()
if(BUILD_TESTING)
add_subdirectory(test)

View File

@@ -16,6 +16,7 @@ environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
ADDRMD: 32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
TOOLSET: msvc-12.0,msvc-14.0
ADDRMD: 32,64
@@ -29,7 +30,7 @@ environment:
ADDRMD: 64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2
CXXSTD: 14,17
CXXSTD: 14,17,latest
ADDRMD: 32,64
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
ADDPATH: C:\cygwin\bin;

View File

@@ -14,6 +14,8 @@ Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes
:idprefix:
:listing-caption: Code Example
:docinfo: private-footer
:source-highlighter: rouge
:source-language: c++
:leveloffset: +1
@@ -37,6 +39,7 @@ include::smart_ptr/pointer_to_other.adoc[]
include::smart_ptr/atomic_shared_ptr.adoc[]
include::smart_ptr/owner_less.adoc[]
include::smart_ptr/owner_equal_to.adoc[]
include::smart_ptr/owner_hash.adoc[]
// appendix
include::smart_ptr/techniques.adoc[]

View File

@@ -1,5 +1,5 @@
////
Copyright 2019 Peter Dimov
Copyright 2019, 2020 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
@@ -16,7 +16,11 @@ http://www.boost.org/LICENSE_1_0.txt
## Changes in 1.74.0
* Added `owner_equals` to `shared_ptr`, `weak_ptr`, `local_shared_ptr`
* Added `owner_equal_to`
* Added `owner_hash_value` to `shared_ptr`, `weak_ptr`
* Added `owner_equal_to`, `owner_hash`
* Added `std::hash` specializations for `shared_ptr`, `local_shared_ptr`
* Added `boost::hash` support to, and `std::hash`, `std::equal_to`
specializations for, `weak_ptr`
## Changes in 1.72.0

View File

@@ -0,0 +1,56 @@
////
Copyright 2020 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////
[#owner_hash]
# owner_hash
:toc:
:toc-title:
:idprefix: owner_hash_to_
## Description
`owner_hash<T>` is a helper function object that takes a smart pointer `p`
and returns `p.owner_hash_value()`. It's useful for creating unordered
containers of `shared_ptr` that use ownership-based equality, instead of
the default pointer value equality. (It can be used with `weak_ptr` too,
but there's no need, because `boost::hash` and `std::hash` for `weak_ptr`
already use ownership-based equality.)
## Example
```
std::unordered_set< boost::shared_ptr<void>,
boost::owner_hash< boost::shared_ptr<void> >,
boost::owner_equal_to< boost::shared_ptr<void> > > set;
```
## Synopsis
`owner_hash` is defined in `<boost/smart_ptr/owner_hash.hpp>`.
```
namespace boost {
template<class T> struct owner_hash
{
typedef std::size_t result_type;
typedef T argument_type;
std::size_t operator()( T const & p ) const noexcept;
};
}
```
## Members
```
std::size_t operator()( T const & p ) const noexcept;
```
[none]
* {blank}
+
Returns::
`p.owner_hash_value()`.

View File

@@ -183,6 +183,8 @@ namespace boost {
template<class Y> bool owner_equals(shared_ptr<Y> const & r) const noexcept;
template<class Y> bool owner_equals(weak_ptr<Y> const & r) const noexcept;
std::size_t owner_hash_value() const noexcept;
};
template<class T, class U>
@@ -677,6 +679,17 @@ template<class Y> bool owner_equals(weak_ptr<Y> const & r) const noexcept;
Returns::
`true` if and only if `*this` and `r` share ownership or are both empty.
### owner_hash_value
```
std::size_t owner_hash_value() const noexcept;
```
[none]
* {blank}
+
Returns::
An unspecified hash value such that two instances that share ownership
have the same hash value.
## Free Functions
### comparison

View File

@@ -115,6 +115,8 @@ namespace boost {
template<class Y> bool owner_equals( weak_ptr<Y> const & r ) const noexcept;
template<class Y> bool owner_equals( shared_ptr<Y> const & r ) const noexcept;
std::size_t owner_hash_value() const noexcept;
};
template<class T, class U>
@@ -298,6 +300,17 @@ template<class Y> bool owner_equals( shared_ptr<Y> const & r ) const noexcept;
Returns::
`true` if and only if `*this` and `r` share ownership or are both empty.
### owner_hash_value
```
std::size_t owner_hash_value() const noexcept;
```
[none]
* {blank}
+
Returns::
An unspecified hash value such that two instances that share ownership
have the same hash value.
## Free Functions
### comparison

View File

@@ -43,8 +43,9 @@
// Memory Ordering: acquire/release
//
#include <boost/smart_ptr/detail/sp_has_gcc_intrinsics.hpp>
#include <boost/smart_ptr/detail/sp_has_sync_intrinsics.hpp>
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
#if defined( BOOST_AC_DISABLE_THREADS )
# include <boost/smart_ptr/detail/atomic_count_nt.hpp>
@@ -73,15 +74,18 @@
#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_SP_HAS_GCC_INTRINSICS )
# include <boost/smart_ptr/detail/atomic_count_gcc_atomic.hpp>
#elif !defined( BOOST_NO_CXX11_HDR_ATOMIC )
# include <boost/smart_ptr/detail/atomic_count_std_atomic.hpp>
#elif defined( BOOST_SP_HAS_SYNC_INTRINSICS )
# include <boost/smart_ptr/detail/atomic_count_sync.hpp>
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined( __PATHSCALE__ )
# include <boost/smart_ptr/detail/atomic_count_gcc_x86.hpp>
#elif defined( BOOST_SP_HAS_SYNC )
# include <boost/smart_ptr/detail/atomic_count_sync.hpp>
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# include <boost/smart_ptr/detail/atomic_count_win32.hpp>

View File

@@ -0,0 +1,63 @@
#ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_ATOMIC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_ATOMIC_HPP_INCLUDED
// boost/detail/atomic_count_gcc_atomic.hpp
//
// atomic_count for g++ 4.7+
//
// Copyright 2007, 2020 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/cstdint.hpp>
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Using __atomic atomic_count")
#endif
namespace boost
{
namespace detail
{
class atomic_count
{
public:
explicit atomic_count( long v ): value_( static_cast< boost::int_least32_t >( v ) )
{
}
long operator++()
{
return __atomic_add_fetch( &value_, +1, __ATOMIC_ACQ_REL );
}
long operator--()
{
return __atomic_add_fetch( &value_, -1, __ATOMIC_ACQ_REL );
}
operator long() const
{
return __atomic_load_n( &value_, __ATOMIC_ACQUIRE );
}
private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
boost::int_least32_t value_;
};
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_ATOMIC_COUNT_GCC_ATOMIC_HPP_INCLUDED

View File

@@ -13,6 +13,8 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/smart_ptr/detail/sp_obsolete.hpp>
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
#include <boost/config/pragma_message.hpp>
@@ -20,6 +22,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/x86 atomic_count")
#endif
BOOST_SP_OBSOLETE()
namespace boost
{

View File

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

View File

@@ -15,6 +15,8 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/cstdint.hpp>
#if defined( __ia64__ ) && defined( __INTEL_COMPILER )
# include <ia64intrin.h>
#endif
@@ -36,7 +38,9 @@ class atomic_count
{
public:
explicit atomic_count( long v ) : value_( v ) {}
explicit atomic_count( long v ): value_( static_cast< boost::int_least32_t >( v ) )
{
}
long operator++()
{
@@ -58,7 +62,7 @@ private:
atomic_count(atomic_count const &);
atomic_count & operator=(atomic_count const &);
mutable long value_;
mutable boost::int_least32_t value_;
};
} // namespace detail

View File

@@ -22,28 +22,25 @@
# pragma warn -8027 // Functions containing try are not expanded inline
#endif
#include <boost/config.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/bad_weak_ptr.hpp>
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
#include <boost/smart_ptr/detail/sp_counted_impl.hpp>
#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/core/addressof.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
// In order to avoid circular dependencies with Boost.TR1
// we make sure that our include of <memory> doesn't try to
// pull in the TR1 headers: that's why we use this header
// rather than including <memory> directly:
#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
#include <boost/cstdint.hpp>
#include <memory> // std::auto_ptr
#include <functional> // std::less
#include <cstddef> // std::size_t
#ifdef BOOST_NO_EXCEPTIONS
# include <new> // std::bad_alloc
#endif
#include <boost/core/addressof.hpp>
#if defined( BOOST_SP_DISABLE_DEPRECATED )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@@ -103,6 +100,14 @@ template< class D > struct sp_convert_reference< D& >
typedef sp_reference_wrapper< D > type;
};
template<class T> std::size_t sp_hash_pointer( T* p ) BOOST_NOEXCEPT
{
boost::uintptr_t v = reinterpret_cast<boost::uintptr_t>( p );
// match boost::hash<T*>
return static_cast<std::size_t>( v + ( v >> 3 ) );
}
class weak_count;
class shared_count
@@ -382,7 +387,7 @@ public:
{
typedef typename sp_convert_reference<D>::type D2;
D2 d2( r.get_deleter() );
D2 d2( static_cast<D&&>( r.get_deleter() ) );
pi_ = new sp_counted_impl_pd< typename std::unique_ptr<Y, D>::pointer, D2 >( r.get(), d2 );
#ifdef BOOST_NO_EXCEPTIONS
@@ -517,6 +522,11 @@ public:
{
return pi_? pi_->get_untyped_deleter(): 0;
}
std::size_t hash_value() const BOOST_SP_NOEXCEPT
{
return sp_hash_pointer( pi_ );
}
};
@@ -643,6 +653,11 @@ public:
{
return std::less<sp_counted_base *>()( pi_, r.pi_ );
}
std::size_t hash_value() const BOOST_SP_NOEXCEPT
{
return sp_hash_pointer( pi_ );
}
};
inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )

View File

@@ -17,14 +17,9 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/smart_ptr/detail/sp_has_gcc_intrinsics.hpp>
#include <boost/smart_ptr/detail/sp_has_sync_intrinsics.hpp>
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
#if !defined( __c2__ ) && defined( __clang__ ) && defined( __has_extension )
# if __has_extension( __c_atomic__ )
# define BOOST_SP_HAS_CLANG_C11_ATOMICS
# endif
#endif
#if defined( BOOST_SP_DISABLE_THREADS )
# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
@@ -41,18 +36,24 @@
#elif defined( BOOST_DISABLE_THREADS ) && !defined( BOOST_SP_ENABLE_THREADS ) && !defined( BOOST_DISABLE_WIN32 )
# include <boost/smart_ptr/detail/sp_counted_base_nt.hpp>
#elif defined( BOOST_SP_HAS_CLANG_C11_ATOMICS )
# include <boost/smart_ptr/detail/sp_counted_base_clang.hpp>
#elif defined( BOOST_SP_HAS_GCC_INTRINSICS )
# include <boost/smart_ptr/detail/sp_counted_base_gcc_atomic.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>
#elif defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 )
# include <boost/smart_ptr/detail/sp_counted_base_sync.hpp>
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) && !defined(__PATHSCALE__)
# include <boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp>
#elif defined( BOOST_SP_HAS_SYNC_INTRINSICS )
# include <boost/smart_ptr/detail/sp_counted_base_sync.hpp>
#elif defined( __SNC__ )
# include <boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp>
#elif defined(__HP_aCC) && defined(__ia64)
# include <boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp>
@@ -71,9 +72,6 @@
#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 )
# include <boost/smart_ptr/detail/sp_counted_base_sync.hpp>
#elif defined(__GNUC__) && ( defined( __sparcv9 ) || ( defined( __sparcv8 ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 402 ) ) )
# include <boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp>
@@ -91,6 +89,4 @@
#endif
#undef BOOST_SP_HAS_CLANG_C11_ATOMICS
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_HPP_INCLUDED

View File

@@ -16,6 +16,7 @@
//
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_obsolete.hpp>
#include <boost/config.hpp>
#include <machine/sys/inline.h>
@@ -26,6 +27,8 @@ BOOST_PRAGMA_MESSAGE("Using HP aCC++/HP-UX/IA64 sp_counted_base")
#endif
BOOST_SP_OBSOLETE()
namespace boost
{

View File

@@ -1,168 +0,0 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// detail/sp_counted_base_clang.hpp - __c11 clang intrinsics
//
// Copyright (c) 2007, 2013, 2015 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Using Clang/C11 sp_counted_base")
#endif
namespace boost
{
namespace detail
{
#if defined(__clang__)
# pragma clang diagnostic push
#endif
#if defined(__clang__) && defined(__has_warning)
# if __has_warning( "-Wc11-extensions" )
# pragma clang diagnostic ignored "-Wc11-extensions"
# endif
#endif
typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t;
inline void atomic_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
__c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED );
}
inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
return __c11_atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL );
}
inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{
// long r = *pw;
// if( r != 0 ) ++*pw;
// return r;
boost::int_least32_t r = __c11_atomic_load( pw, __ATOMIC_RELAXED );
for( ;; )
{
if( r == 0 )
{
return r;
}
if( __c11_atomic_compare_exchange_weak( pw, &r, r + 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED ) )
{
return r;
}
}
}
#if defined(__clang__)
# pragma clang diagnostic ignored "-Wweak-vtables"
#endif
class BOOST_SYMBOL_VISIBLE sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
atomic_int_least32_t use_count_; // #shared
atomic_int_least32_t weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base() BOOST_SP_NOEXCEPT
{
__c11_atomic_init( &use_count_, 1 );
__c11_atomic_init( &weak_count_, 1 );
}
virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
{
}
// dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this.
virtual void dispose() BOOST_SP_NOEXCEPT = 0; // nothrow
// destroy() is called when weak_count_ drops to zero.
virtual void destroy() BOOST_SP_NOEXCEPT // nothrow
{
delete this;
}
virtual void * get_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_local_deleter( sp_typeinfo_ const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy() BOOST_SP_NOEXCEPT
{
atomic_increment( &use_count_ );
}
bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
{
return atomic_conditional_increment( &use_count_ ) != 0;
}
void release() BOOST_SP_NOEXCEPT
{
if( atomic_decrement( &use_count_ ) == 1 )
{
dispose();
weak_release();
}
}
void weak_add_ref() BOOST_SP_NOEXCEPT
{
atomic_increment( &weak_count_ );
}
void weak_release() BOOST_SP_NOEXCEPT
{
if( atomic_decrement( &weak_count_ ) == 1 )
{
destroy();
}
}
long use_count() const BOOST_SP_NOEXCEPT
{
return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE );
}
};
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CLANG_HPP_INCLUDED

View File

@@ -25,6 +25,7 @@
//
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_obsolete.hpp>
#include <boost/config.hpp>
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
@@ -34,6 +35,8 @@ BOOST_PRAGMA_MESSAGE("Using CodeWarrior/PowerPC sp_counted_base")
#endif
BOOST_SP_OBSOLETE()
namespace boost
{

View File

@@ -1,5 +1,5 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
#ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_ATOMIC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_GCC_ATOMIC_HPP_INCLUDED
// MS compatible compilers support #pragma once
@@ -7,31 +7,20 @@
# pragma once
#endif
// detail/sp_counted_base_gcc_atomic.hpp - g++ 4.7+ __atomic intrinsics
//
// detail/sp_counted_base_cw_x86.hpp - CodeWarrion on 486+
//
// Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
// Copyright 2004-2005 Peter Dimov
// Copyright 2005 Rene Rivera
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
//
// Lock-free algorithm by Alexander Terekhov
//
// Thanks to Ben Hitchings for the #weak + (#shared != 0)
// formulation
//
// Copyright 2007, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Using CodeWarrior/x86 sp_counted_base")
BOOST_PRAGMA_MESSAGE("Using __atomic sp_counted_base")
#endif
@@ -41,50 +30,41 @@ namespace boost
namespace detail
{
inline int atomic_exchange_and_add( int * pw, int dv )
inline void atomic_increment( boost::uint_least32_t * pw )
{
// int r = *pw;
// *pw += dv;
__atomic_fetch_add( pw, 1, __ATOMIC_RELAXED );
}
inline boost::uint_least32_t atomic_decrement( boost::uint_least32_t * pw )
{
return __atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL );
}
inline boost::uint_least32_t atomic_conditional_increment( boost::uint_least32_t * pw )
{
// long r = *pw;
// if( r != 0 ) ++*pw;
// return r;
asm
boost::uint_least32_t r = __atomic_load_n( pw, __ATOMIC_RELAXED );
for( ;; )
{
mov esi, [pw]
mov eax, dv
lock xadd dword ptr [esi], eax
if( r == 0 )
{
return r;
}
if( __atomic_compare_exchange_n( pw, &r, r + 1, true, __ATOMIC_RELAXED, __ATOMIC_RELAXED ) )
{
return r;
}
}
}
inline void atomic_increment( int * pw )
inline boost::uint_least32_t atomic_load( boost::uint_least32_t const * pw )
{
//atomic_exchange_and_add( pw, 1 );
asm
{
mov esi, [pw]
lock inc dword ptr [esi]
}
}
inline int atomic_conditional_increment( int * pw )
{
// int rv = *pw;
// if( rv != 0 ) ++*pw;
// return rv;
asm
{
mov esi, [pw]
mov eax, dword ptr [esi]
L0:
test eax, eax
je L1
mov ebx, eax
inc ebx
lock cmpxchg dword ptr [esi], ebx
jne L0
L1:
}
return __atomic_load_n( pw, __ATOMIC_ACQUIRE );
}
class BOOST_SYMBOL_VISIBLE sp_counted_base
@@ -94,8 +74,8 @@ private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
boost::uint_least32_t use_count_; // #shared
boost::uint_least32_t weak_count_; // #weak + (#shared != 0)
public:
@@ -135,7 +115,7 @@ public:
void release() // nothrow
{
if( atomic_exchange_and_add( &use_count_, -1 ) == 1 )
if( atomic_decrement( &use_count_ ) == 1 )
{
dispose();
weak_release();
@@ -149,7 +129,7 @@ public:
void weak_release() // nothrow
{
if( atomic_exchange_and_add( &weak_count_, -1 ) == 1 )
if( atomic_decrement( &weak_count_ ) == 1 )
{
destroy();
}
@@ -157,7 +137,7 @@ public:
long use_count() const // nothrow
{
return static_cast<int const volatile &>( use_count_ );
return atomic_load( &use_count_ );
}
};
@@ -165,4 +145,4 @@ public:
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_CW_X86_HPP_INCLUDED
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_COUNTED_BASE_SYNC_HPP_INCLUDED

View File

@@ -17,6 +17,7 @@
//
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_obsolete.hpp>
#include <boost/config.hpp>
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
@@ -26,6 +27,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/IA64 sp_counted_base")
#endif
BOOST_SP_OBSOLETE()
namespace boost
{

View File

@@ -21,6 +21,7 @@
//
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_obsolete.hpp>
#include <boost/config.hpp>
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
@@ -30,6 +31,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/MIPS sp_counted_base")
#endif
BOOST_SP_OBSOLETE()
namespace boost
{

View File

@@ -25,6 +25,7 @@
//
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_obsolete.hpp>
#include <boost/config.hpp>
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
@@ -34,6 +35,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/PowerPC sp_counted_base")
#endif
BOOST_SP_OBSOLETE()
namespace boost
{

View File

@@ -20,6 +20,7 @@
// Thanks to Michael van der Westhuizen
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_obsolete.hpp>
#include <boost/config.hpp>
#include <inttypes.h> // int32_t
@@ -30,6 +31,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/Sparc sp_counted_base")
#endif
BOOST_SP_OBSOLETE()
namespace boost
{

View File

@@ -25,6 +25,7 @@
//
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_obsolete.hpp>
#include <boost/config.hpp>
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
@@ -34,6 +35,8 @@ BOOST_PRAGMA_MESSAGE("Using g++/x86 sp_counted_base")
#endif
BOOST_SP_OBSOLETE()
namespace boost
{

View File

@@ -20,6 +20,7 @@
// Thanks to Michael van der Westhuizen
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_obsolete.hpp>
#include <boost/config.hpp>
#include <inttypes.h> // uint32_t
@@ -30,6 +31,8 @@ BOOST_PRAGMA_MESSAGE("Using PS3 sp_counted_base")
#endif
BOOST_SP_OBSOLETE()
namespace boost
{

View File

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

View File

@@ -22,6 +22,7 @@
//
#include <boost/smart_ptr/detail/sp_typeinfo_.hpp>
#include <boost/smart_ptr/detail/sp_obsolete.hpp>
#include <boost/config.hpp>
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
@@ -31,6 +32,8 @@ BOOST_PRAGMA_MESSAGE("Using xlC/PowerPC sp_counted_base")
#endif
BOOST_SP_OBSOLETE()
extern "builtin" void __lwsync(void);
extern "builtin" void __isync(void);
extern "builtin" int __fetch_and_add(volatile int* addr, int val);

View File

@@ -18,25 +18,21 @@
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/config.hpp>
#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
#endif
#include <boost/checked_delete.hpp>
#include <boost/smart_ptr/detail/sp_counted_base.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/checked_delete.hpp>
#include <boost/core/addressof.hpp>
#include <boost/config.hpp>
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
#include <boost/smart_ptr/detail/quick_allocator.hpp>
#endif
#if defined(BOOST_SP_USE_STD_ALLOCATOR)
#include <memory> // std::allocator
#endif
#include <memory> // std::allocator, std::allocator_traits
#include <cstddef> // std::size_t
namespace boost
@@ -149,7 +145,7 @@ template<class P, class D> class BOOST_SYMBOL_VISIBLE sp_counted_impl_pd: public
private:
P ptr; // copy constructor must not throw
D del; // copy constructor must not throw
D del; // copy/move constructor must not throw
sp_counted_impl_pd( sp_counted_impl_pd const & );
sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
@@ -160,10 +156,20 @@ public:
// pre: d(p) must not throw
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
sp_counted_impl_pd( P p, D & d ): ptr( p ), del( static_cast< D&& >( d ) )
{
}
#else
sp_counted_impl_pd( P p, D & d ): ptr( p ), del( d )
{
}
#endif
sp_counted_impl_pd( P p ): ptr( p ), del()
{
}
@@ -222,7 +228,7 @@ template<class P, class D, class A> class BOOST_SYMBOL_VISIBLE sp_counted_impl_p
private:
P p_; // copy constructor must not throw
D d_; // copy constructor must not throw
D d_; // copy/move constructor must not throw
A a_; // copy constructor must not throw
sp_counted_impl_pda( sp_counted_impl_pda const & );
@@ -234,10 +240,20 @@ public:
// pre: d( p ) must not throw
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
sp_counted_impl_pda( P p, D & d, A a ): p_( p ), d_( static_cast< D&& >( d ) ), a_( a )
{
}
#else
sp_counted_impl_pda( P p, D & d, A a ): p_( p ), d_( d ), a_( a )
{
}
#endif
sp_counted_impl_pda( P p, A a ): p_( p ), d_( a ), a_( a )
{
}

View File

@@ -0,0 +1,27 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_GCC_INTRINSICS_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_HAS_GCC_INTRINSICS_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// boost/smart_ptr/detail/sp_has_gcc_intrinsics.hpp
//
// Copyright 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
//
// Defines the BOOST_SP_HAS_GCC_INTRINSICS macro if the __atomic_*
// intrinsics are available.
#if defined( __ATOMIC_RELAXED ) && defined( __ATOMIC_ACQUIRE ) && defined( __ATOMIC_RELEASE ) && defined( __ATOMIC_ACQ_REL )
# define BOOST_SP_HAS_GCC_INTRINSICS
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_GCC_INTRINSICS_HPP_INCLUDED

View File

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

View File

@@ -0,0 +1,69 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_INTRINSICS_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_INTRINSICS_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
//
// boost/smart_ptr/detail/sp_has_sync_intrinsics.hpp
//
// Copyright (c) 2008, 2009 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Defines the BOOST_SP_HAS_SYNC_INTRINSICS macro if the __sync_* intrinsics
// are available.
//
#if !defined( BOOST_SP_NO_SYNC_INTRINSICS ) && !defined( BOOST_SP_NO_SYNC )
#if defined( __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 ) && !defined( __c2__ )
# define BOOST_SP_HAS_SYNC_INTRINSICS
#elif defined( __IBMCPP__ ) && ( __IBMCPP__ >= 1210 ) && !defined( __COMPILER_VER__ )
# define BOOST_SP_HAS_SYNC_INTRINSICS
#elif defined( __GNUC__ ) && ( __GNUC__ * 100 + __GNUC_MINOR__ >= 401 ) && !defined( __c2__ )
#define BOOST_SP_HAS_SYNC_INTRINSICS
#if defined( __arm__ ) || defined( __armel__ )
#undef BOOST_SP_HAS_SYNC_INTRINSICS
#endif
#if defined( __hppa ) || defined( __hppa__ )
#undef BOOST_SP_HAS_SYNC_INTRINSICS
#endif
#if defined( __m68k__ )
#undef BOOST_SP_HAS_SYNC_INTRINSICS
#endif
#if defined( __sh__ )
#undef BOOST_SP_HAS_SYNC_INTRINSICS
#endif
#if defined( __sparc__ )
#undef BOOST_SP_HAS_SYNC_INTRINSICS
#endif
#if defined( __INTEL_COMPILER ) && !defined( __ia64__ ) && ( __INTEL_COMPILER < 1110 )
#undef BOOST_SP_HAS_SYNC_INTRINSICS
#endif
#if defined(__PATHSCALE__) && ((__PATHCC__ == 4) && (__PATHCC_MINOR__ < 9))
#undef BOOST_SP_HAS_SYNC_INTRINSICS
#endif
#endif
#endif // #if !defined( BOOST_SP_NO_SYNC_INTRINSICS ) && !defined( BOOST_SP_NO_SYNC )
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_HAS_SYNC_INTRINSICS_HPP_INCLUDED

View File

@@ -0,0 +1,32 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_OBSOLETE_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_OBSOLETE_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// boost/smart_ptr/detail/sp_obsolete.hpp
//
// Copyright 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
//
// Defines the BOOST_SP_OBSOLETE macro that emits a deprecation
// message.
#include <boost/config/pragma_message.hpp>
#if !defined( BOOST_SP_NO_OBSOLETE_MESSAGE )
#define BOOST_SP_OBSOLETE() BOOST_PRAGMA_MESSAGE("This platform-specific implementation is presumed obsolete and is slated for removal. If you want it retained, please open an issue in https://github.com/boostorg/smart_ptr.")
#else
#define BOOST_SP_OBSOLETE()
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_OBSOLETE_HPP_INCLUDED

View File

@@ -0,0 +1,51 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// boost/smart_ptr/detail/sp_thread_pause.hpp
//
// inline void bost::detail::sp_thread_pause();
//
// Emits a "pause" instruction.
//
// Copyright 2008, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0
// https://www.boost.org/LICENSE_1_0.txt
#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) && !defined(__c2__)
extern "C" void _mm_pause();
#define BOOST_SP_PAUSE _mm_pause();
#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
#define BOOST_SP_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
#else
#define BOOST_SP_PAUSE
#endif
namespace boost
{
namespace detail
{
inline void sp_thread_pause()
{
BOOST_SP_PAUSE
}
} // namespace detail
} // namespace boost
#undef BOOST_SP_PAUSE
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED

View File

@@ -0,0 +1,104 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// boost/smart_ptr/detail/sp_thread_sleep.hpp
//
// inline void bost::detail::sp_thread_sleep();
//
// Cease execution for a while to yield to other threads,
// as if by calling nanosleep() with an appropriate interval.
//
// Copyright 2008, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using Sleep(1) in sp_thread_sleep")
#endif
#include <boost/smart_ptr/detail/sp_win32_sleep.hpp>
namespace boost
{
namespace detail
{
inline void sp_thread_sleep()
{
Sleep( 1 );
}
} // namespace detail
} // namespace boost
#elif defined(BOOST_HAS_NANOSLEEP)
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using nanosleep() in sp_thread_sleep")
#endif
#include <time.h>
namespace boost
{
namespace detail
{
inline void sp_thread_sleep()
{
// g++ -Wextra warns on {} or {0}
struct timespec rqtp = { 0, 0 };
// POSIX says that timespec has tv_sec and tv_nsec
// But it doesn't guarantee order or placement
rqtp.tv_sec = 0;
rqtp.tv_nsec = 1000;
nanosleep( &rqtp, 0 );
}
} // namespace detail
} // namespace boost
#else
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using sp_thread_yield() in sp_thread_sleep")
#endif
#include <boost/smart_ptr/detail/sp_thread_yield.hpp>
namespace boost
{
namespace detail
{
inline void sp_thread_sleep()
{
sp_thread_yield();
}
} // namespace detail
} // namespace boost
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED

View File

@@ -0,0 +1,100 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// boost/smart_ptr/detail/sp_thread_yield.hpp
//
// inline void bost::detail::sp_thread_yield();
//
// Gives up the remainder of the time slice,
// as if by calling sched_yield().
//
// Copyright 2008, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using Sleep(0) in sp_thread_yield")
#endif
#include <boost/smart_ptr/detail/sp_win32_sleep.hpp>
namespace boost
{
namespace detail
{
inline void sp_thread_yield()
{
Sleep( 0 );
}
} // namespace detail
} // namespace boost
#elif defined(BOOST_HAS_SCHED_YIELD)
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using sched_yield() in sp_thread_yield")
#endif
#ifndef _AIX
# include <sched.h>
#else
// AIX's sched.h defines ::var which sometimes conflicts with Lambda's var
extern "C" int sched_yield(void);
#endif
namespace boost
{
namespace detail
{
inline void sp_thread_yield()
{
sched_yield();
}
} // namespace detail
} // namespace boost
#else
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using sp_thread_pause() in sp_thread_yield")
#endif
#include <boost/smart_ptr/detail/sp_thread_pause.hpp>
namespace boost
{
namespace detail
{
inline void sp_thread_yield()
{
sp_thread_pause();
}
} // namespace detail
} // namespace boost
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED

View File

@@ -0,0 +1,49 @@
#ifndef BOOST_SMART_PTR_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// boost/smart_ptr/detail/sp_win32_sleep.hpp
//
// Declares the Win32 Sleep() function.
//
// Copyright 2008, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0
// https://www.boost.org/LICENSE_1_0.txt
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
#endif
namespace boost
{
namespace detail
{
#if !defined( BOOST_USE_WINDOWS_H )
#if defined(__clang__) && defined(__x86_64__)
// clang x64 warns that __stdcall is ignored
# define BOOST_SP_STDCALL
#else
# define BOOST_SP_STDCALL __stdcall
#endif
#if defined(__LP64__) // Cygwin 64
extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned int ms );
#else
extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned long ms );
#endif
#undef BOOST_SP_STDCALL
#endif // !defined( BOOST_USE_WINDOWS_H )
} // namespace detail
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED

View File

@@ -28,28 +28,26 @@
// #define BOOST_DETAIL_SPINLOCK_INIT <unspecified>
//
#include <boost/smart_ptr/detail/sp_has_gcc_intrinsics.hpp>
#include <boost/smart_ptr/detail/sp_has_sync_intrinsics.hpp>
#include <boost/config.hpp>
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
#if defined( BOOST_SP_USE_STD_ATOMIC )
# if !defined( __clang__ )
# include <boost/smart_ptr/detail/spinlock_std_atomic.hpp>
# else
// Clang (at least up to 3.4) can't compile spinlock_pool when
// using std::atomic, so substitute the __sync implementation instead.
# include <boost/smart_ptr/detail/spinlock_sync.hpp>
# endif
#elif defined( BOOST_SP_USE_PTHREADS )
# include <boost/smart_ptr/detail/spinlock_pt.hpp>
#elif defined( BOOST_SP_HAS_GCC_INTRINSICS )
# include <boost/smart_ptr/detail/spinlock_gcc_atomic.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>
#elif defined( BOOST_SP_HAS_SYNC )
#elif defined( BOOST_SP_HAS_SYNC_INTRINSICS )
# include <boost/smart_ptr/detail/spinlock_sync.hpp>
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)

View File

@@ -0,0 +1,85 @@
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ATOMIC_HPP_INCLUDED
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ATOMIC_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// Copyright 2008, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/smart_ptr/detail/yield_k.hpp>
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Using __atomic spinlock")
#endif
namespace boost
{
namespace detail
{
class spinlock
{
public:
unsigned char v_;
public:
bool try_lock()
{
return __atomic_test_and_set( &v_, __ATOMIC_ACQUIRE ) == 0;
}
void lock()
{
for( unsigned k = 0; !try_lock(); ++k )
{
boost::detail::yield( k );
}
}
void unlock()
{
__atomic_clear( &v_, __ATOMIC_RELEASE );
}
public:
class scoped_lock
{
private:
spinlock & sp_;
scoped_lock( scoped_lock const & );
scoped_lock & operator=( scoped_lock const & );
public:
explicit scoped_lock( spinlock & sp ): sp_( sp )
{
sp.lock();
}
~scoped_lock()
{
sp_.unlock();
}
};
};
} // namespace detail
} // namespace boost
#define BOOST_DETAIL_SPINLOCK_INIT {0}
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_GCC_ATOMIC_HPP_INCLUDED

View File

@@ -38,7 +38,7 @@ class spinlock
{
public:
int v_;
unsigned char v_;
public:

View File

@@ -7,107 +7,22 @@
# pragma once
#endif
// boost/smart_ptr/detail/yield_k.hpp
//
// yield_k.hpp
// Copyright 2008, 2020 Peter Dimov
//
// Copyright (c) 2008 Peter Dimov
//
// void yield( unsigned k );
// inline void boost::detail::yield( unsigned k );
//
// Typical use:
//
// for( unsigned k = 0; !try_lock(); ++k ) yield( k );
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/smart_ptr/detail/sp_thread_pause.hpp>
#include <boost/smart_ptr/detail/sp_thread_sleep.hpp>
#include <boost/config.hpp>
// BOOST_SMT_PAUSE
#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) && !defined(__c2__)
extern "C" void _mm_pause();
#define BOOST_SMT_PAUSE _mm_pause();
#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
#define BOOST_SMT_PAUSE __asm__ __volatile__( "rep; nop" : : : "memory" );
#endif
//
#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
#endif
namespace boost
{
namespace detail
{
#if !defined( BOOST_USE_WINDOWS_H )
#if defined(__clang__) && defined(__x86_64__)
// clang x64 warns that __stdcall is ignored
# define BOOST_SP_STDCALL
#else
# define BOOST_SP_STDCALL __stdcall
#endif
#if defined(__LP64__) // Cygwin 64
extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned int ms );
#else
extern "C" __declspec(dllimport) void BOOST_SP_STDCALL Sleep( unsigned long ms );
#endif
#undef BOOST_SP_STDCALL
#endif // !defined( BOOST_USE_WINDOWS_H )
inline void yield( unsigned k ) BOOST_NOEXCEPT
{
if( k < 4 )
{
}
#if defined( BOOST_SMT_PAUSE )
else if( k < 16 )
{
BOOST_SMT_PAUSE
}
#endif
else if( k < 32 )
{
Sleep( 0 );
}
else
{
Sleep( 1 );
}
}
} // namespace detail
} // namespace boost
#elif defined( BOOST_HAS_PTHREADS )
#ifndef _AIX
#include <sched.h>
#else
// AIX's sched.h defines ::var which sometimes conflicts with Lambda's var
extern "C" int sched_yield(void);
#endif
#include <time.h>
namespace boost
{
@@ -116,31 +31,16 @@ namespace detail
inline void yield( unsigned k )
{
if( k < 4 )
// Experiments on Windows and Fedora 32 show that a single pause,
// followed by an immediate sp_thread_sleep(), is best.
if( k == 0 )
{
}
#if defined( BOOST_SMT_PAUSE )
else if( k < 16 )
{
BOOST_SMT_PAUSE
}
#endif
else if( k < 32 || k & 1 )
{
sched_yield();
sp_thread_pause();
}
else
{
// g++ -Wextra warns on {} or {0}
struct timespec rqtp = { 0, 0 };
// POSIX says that timespec has tv_sec and tv_nsec
// But it doesn't guarantee order or placement
rqtp.tv_sec = 0;
rqtp.tv_nsec = 1000;
nanosleep( &rqtp, 0 );
sp_thread_sleep();
}
}
@@ -148,22 +48,4 @@ inline void yield( unsigned k )
} // namespace boost
#else
namespace boost
{
namespace detail
{
inline void yield( unsigned )
{
}
} // namespace detail
} // namespace boost
#endif
#endif // #ifndef BOOST_SMART_PTR_DETAIL_YIELD_K_HPP_INCLUDED

View File

@@ -0,0 +1,27 @@
#ifndef BOOST_SMART_PTR_OWNER_HASH_HPP_INCLUDED
#define BOOST_SMART_PTR_OWNER_HASH_HPP_INCLUDED
// Copyright 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#include <cstddef>
namespace boost
{
template<class T> struct owner_hash
{
typedef std::size_t result_type;
typedef T argument_type;
std::size_t operator()( T const & t ) const BOOST_NOEXCEPT
{
return t.owner_hash_value();
}
};
} // namespace boost
#endif // #ifndef BOOST_SMART_PTR_OWNER_HASH_HPP_INCLUDED

View File

@@ -14,23 +14,16 @@
// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <boost/config.hpp> // for broken compiler workarounds
// In order to avoid circular dependencies with Boost.TR1
// we make sure that our include of <memory> doesn't try to
// pull in the TR1 headers: that's why we use this header
// rather than including <memory> directly:
#include <boost/config/no_tr1/memory.hpp> // std::auto_ptr
#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/smart_ptr/detail/shared_count.hpp>
#include <boost/config/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_disable_deprecated.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/checked_delete.hpp>
#include <boost/throw_exception.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
#include <boost/smart_ptr/detail/spinlock_pool.hpp>
@@ -40,6 +33,7 @@
#include <functional> // for std::less
#include <typeinfo> // for std::bad_cast
#include <cstddef> // for std::size_t
#include <memory> // for std::auto_ptr
#if !defined(BOOST_NO_IOSTREAM)
#if !defined(BOOST_NO_IOSFWD)
@@ -380,39 +374,81 @@ public:
}
//
// Requirements: D's copy constructor must not throw
// Requirements: D's copy/move constructors must not throw
//
// shared_ptr will release p by calling d(p)
//
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, static_cast< D&& >( d ) )
{
boost::detail::sp_deleter_construct( this, p );
}
#else
template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d )
{
boost::detail::sp_deleter_construct( this, p );
}
#endif
#if !defined( BOOST_NO_CXX11_NULLPTR )
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, static_cast< D&& >( d ) )
{
}
#else
template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, d )
{
}
#endif
#endif
// As above, but with allocator. A's copy constructor shall not throw.
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, static_cast< D&& >( d ), a )
{
boost::detail::sp_deleter_construct( this, p );
}
#else
template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
{
boost::detail::sp_deleter_construct( this, p );
}
#endif
#if !defined( BOOST_NO_CXX11_NULLPTR )
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, static_cast< D&& >( d ), a )
{
}
#else
template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, d, a )
{
}
#endif
#endif
// generated copy constructor, destructor are fine...
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
@@ -699,6 +735,20 @@ public:
this_type( p ).swap( *this );
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class Y, class D> void reset( Y * p, D d )
{
this_type( p, static_cast< D&& >( d ) ).swap( *this );
}
template<class Y, class D, class A> void reset( Y * p, D d, A a )
{
this_type( p, static_cast< D&& >( d ), a ).swap( *this );
}
#else
template<class Y, class D> void reset( Y * p, D d )
{
this_type( p, d ).swap( *this );
@@ -709,6 +759,8 @@ public:
this_type( p, d, a ).swap( *this );
}
#endif
template<class Y> void reset( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT
{
this_type( r, p ).swap( *this );
@@ -787,6 +839,11 @@ public:
return pn == rhs.pn;
}
std::size_t owner_hash_value() const BOOST_SP_NOEXCEPT
{
return pn.hash_value();
}
void * _internal_get_deleter( boost::detail::sp_typeinfo_ const & ti ) const BOOST_SP_NOEXCEPT
{
return pn.get_deleter( ti );

View File

@@ -13,10 +13,11 @@
// See http://www.boost.org/libs/smart_ptr/ for documentation.
//
#include <memory> // boost.TR1 include order fix
#include <boost/smart_ptr/detail/shared_count.hpp>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <memory>
#include <cstddef>
namespace boost
{
@@ -247,6 +248,11 @@ public:
return pn == rhs.pn;
}
std::size_t owner_hash_value() const BOOST_SP_NOEXCEPT
{
return pn.hash_value();
}
// Tasteless as this may seem, making all members public allows member templates
// to work in the absence of member template friends. (Matthew Langston)
@@ -280,6 +286,40 @@ template<class T> weak_ptr( shared_ptr<T> ) -> weak_ptr<T>;
#endif
// hash_value
template< class T > std::size_t hash_value( boost::weak_ptr<T> const & p ) BOOST_SP_NOEXCEPT
{
return p.owner_hash_value();
}
} // namespace boost
// std::hash, std::equal_to
namespace std
{
#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
template<class T> struct hash< ::boost::weak_ptr<T> >
{
std::size_t operator()( ::boost::weak_ptr<T> const & p ) const BOOST_SP_NOEXCEPT
{
return p.owner_hash_value();
}
};
#endif // #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
template<class T> struct equal_to< ::boost::weak_ptr<T> >
{
bool operator()( ::boost::weak_ptr<T> const & a, ::boost::weak_ptr<T> const & b ) const BOOST_SP_NOEXCEPT
{
return a.owner_equals( b );
}
};
} // namespace std
#endif // #ifndef BOOST_SMART_PTR_WEAK_PTR_HPP_INCLUDED

View File

@@ -16,6 +16,7 @@
"Memory"
],
"maintainers": [
"Peter Dimov <pdimov -at- pdimov.com>"
]
"Peter Dimov <pdimov -at- gmail.com>"
],
"cxxstd": "03"
}

View File

@@ -81,7 +81,7 @@ run sp_recursive_assign_rv_test.cpp ;
run sp_recursive_assign2_rv_test.cpp ;
compile-fail auto_ptr_lv_fail.cpp
: <toolset>gcc-4.4.7:<build>no ;
: <toolset>gcc-4.4.7:<build>no <toolset>gcc-4.4:<build>no ;
run atomic_count_test2.cpp ;
run sp_typeinfo_test.cpp ;
@@ -331,9 +331,9 @@ run weak_ptr_alias_move_test.cpp ;
run sp_typeinfo_test.cpp : : : <rtti>off : sp_typeinfo_test_no_rtti ;
run get_deleter_test.cpp : : : <rtti>off <toolset>gcc-4.4.7,<cxxstd>0x:<build>no : get_deleter_test_no_rtti ;
run get_deleter_test2.cpp : : : <rtti>off <toolset>gcc-4.4.7,<cxxstd>0x:<build>no : get_deleter_test2_no_rtti ;
run get_deleter_test3.cpp : : : <rtti>off <toolset>gcc-4.4.7,<cxxstd>0x:<build>no : get_deleter_test3_no_rtti ;
run get_deleter_test.cpp : : : <rtti>off <toolset>gcc-4.4.7,<cxxstd>0x:<build>no <toolset>gcc-4.4,<cxxstd>0x:<build>no : get_deleter_test_no_rtti ;
run get_deleter_test2.cpp : : : <rtti>off <toolset>gcc-4.4.7,<cxxstd>0x:<build>no <toolset>gcc-4.4,<cxxstd>0x:<build>no : get_deleter_test2_no_rtti ;
run get_deleter_test3.cpp : : : <rtti>off <toolset>gcc-4.4.7,<cxxstd>0x:<build>no <toolset>gcc-4.4,<cxxstd>0x:<build>no : get_deleter_test3_no_rtti ;
run shared_from_test.cpp ;
run weak_from_test.cpp ;
@@ -398,3 +398,16 @@ run weak_ptr_mt_test.cpp
: : : <threading>multi ;
compile sp_report_implementation.cpp ;
run sp_owner_hash_value_test.cpp ;
run wp_hash_test.cpp ;
run wp_hash_test2.cpp ;
run wp_unordered_test.cpp ;
run owner_hash_test.cpp ;
run sp_unordered_test.cpp ;
run sp_unique_ptr_test2.cpp ;
run sp_move_only_deleter.cpp ;

88
test/owner_hash_test.cpp Normal file
View File

@@ -0,0 +1,88 @@
// Copyright 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/smart_ptr/owner_hash.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
template<class T> std::size_t hash_( T const& t )
{
return boost::owner_hash<T>()( t );
}
int main()
{
boost::shared_ptr<int> p1( new int );
boost::shared_ptr<int> p2( p1 );
BOOST_TEST_EQ( hash_( p1 ), hash_( p2 ) );
boost::shared_ptr<int> p3( new int );
BOOST_TEST_NE( hash_( p1 ), hash_( p3 ) );
boost::shared_ptr<int> p4;
boost::shared_ptr<int> p5;
BOOST_TEST_EQ( hash_( p4 ), hash_( p5 ) );
BOOST_TEST_NE( hash_( p4 ), hash_( p3 ) );
boost::shared_ptr<int> p6( static_cast<int*>(0) );
BOOST_TEST_NE( hash_( p4 ), hash_( p6 ) );
boost::shared_ptr<void> p7( p1 );
BOOST_TEST_EQ( hash_( p1 ), hash_( p7 ) );
boost::shared_ptr<void> p8;
BOOST_TEST_NE( hash_( p1 ), hash_( p8 ) );
BOOST_TEST_EQ( hash_( p4 ), hash_( p8 ) );
boost::weak_ptr<int> q1( p1 );
BOOST_TEST_EQ( hash_( p1 ), hash_( q1 ) );
boost::weak_ptr<int> q2( p1 );
BOOST_TEST_EQ( hash_( q1 ), hash_( q2 ) );
boost::weak_ptr<int> q3( p3 );
BOOST_TEST_NE( hash_( p1 ), hash_( q3 ) );
BOOST_TEST_NE( hash_( q1 ), hash_( q3 ) );
boost::weak_ptr<int> q4;
BOOST_TEST_EQ( hash_( p4 ), hash_( q4 ) );
BOOST_TEST_NE( hash_( q1 ), hash_( q4 ) );
boost::weak_ptr<void> q5;
BOOST_TEST_EQ( hash_( q4 ), hash_( q5 ) );
boost::weak_ptr<void> q7( p7 );
BOOST_TEST_EQ( hash_( p1 ), hash_( q7 ) );
BOOST_TEST_EQ( hash_( q1 ), hash_( q7 ) );
p1.reset();
p2.reset();
p3.reset();
p7.reset();
BOOST_TEST( q1.expired() );
BOOST_TEST( q2.expired() );
BOOST_TEST( q3.expired() );
BOOST_TEST( q7.expired() );
BOOST_TEST_EQ( hash_( q1 ), hash_( q2 ) );
BOOST_TEST_EQ( hash_( q1 ), hash_( q7 ) );
BOOST_TEST_NE( hash_( q1 ), hash_( q3 ) );
BOOST_TEST_NE( hash_( q1 ), hash_( q4 ) );
return boost::report_errors();
}

View File

@@ -0,0 +1,153 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#include <memory>
#include <utility>
#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_NO_CXX11_RVALUE_REFERENCES is defined")
int main() {}
#else
struct Y
{
static int instances;
bool deleted_;
Y(): deleted_( false )
{
++instances;
}
~Y()
{
BOOST_TEST( deleted_ );
--instances;
}
private:
Y( Y const & );
Y & operator=( Y const & );
};
int Y::instances = 0;
struct YD
{
bool moved_;
YD(): moved_( false )
{
}
YD( YD&& r ): moved_( false )
{
r.moved_ = true;
}
void operator()( Y* p ) const
{
BOOST_TEST( !moved_ );
if( p )
{
p->deleted_ = true;
delete p;
}
}
private:
YD( YD const & );
YD & operator=( YD const & );
};
int main()
{
BOOST_TEST( Y::instances == 0 );
{
YD del;
boost::shared_ptr<Y> p( new Y, std::move( del ) );
BOOST_TEST( Y::instances == 1 );
BOOST_TEST( del.moved_ );
p.reset( new Y, YD() );
BOOST_TEST( Y::instances == 1 );
p = boost::shared_ptr<Y>( new Y, YD() );
BOOST_TEST( Y::instances == 1 );
YD del2;
p.reset( new Y, std::move( del2 ) );
BOOST_TEST( Y::instances == 1 );
BOOST_TEST( del2.moved_ );
p.reset();
BOOST_TEST( Y::instances == 0 );
}
{
YD del;
boost::shared_ptr<Y> p( new Y, std::move( del ), std::allocator<Y>() );
BOOST_TEST( Y::instances == 1 );
BOOST_TEST( del.moved_ );
p.reset( new Y, YD(), std::allocator<Y>() );
BOOST_TEST( Y::instances == 1 );
p = boost::shared_ptr<Y>( new Y, YD(), std::allocator<Y>() );
BOOST_TEST( Y::instances == 1 );
YD del2;
p.reset( new Y, std::move( del2 ), std::allocator<Y>() );
BOOST_TEST( Y::instances == 1 );
BOOST_TEST( del2.moved_ );
p.reset();
BOOST_TEST( Y::instances == 0 );
}
#if !defined( BOOST_NO_CXX11_NULLPTR )
{
boost::shared_ptr<Y> p( nullptr, YD() );
YD del;
p = boost::shared_ptr<Y>( nullptr, std::move( del ) );
BOOST_TEST( del.moved_ );
}
{
boost::shared_ptr<Y> p( nullptr, YD(), std::allocator<Y>() );
YD del;
p = boost::shared_ptr<Y>( nullptr, std::move( del ), std::allocator<Y>() );
BOOST_TEST( del.moved_ );
}
#endif
return boost::report_errors();
}
#endif

View File

@@ -0,0 +1,85 @@
// Copyright 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
int main()
{
{
boost::shared_ptr<int> p1( new int );
boost::shared_ptr<int> p2( p1 );
BOOST_TEST_EQ( p1.owner_hash_value(), p2.owner_hash_value() );
boost::shared_ptr<int> p3( new int );
BOOST_TEST_NE( p1.owner_hash_value(), p3.owner_hash_value() );
boost::shared_ptr<int> p4;
boost::shared_ptr<int> p5;
BOOST_TEST_EQ( p4.owner_hash_value(), p5.owner_hash_value() );
BOOST_TEST_NE( p4.owner_hash_value(), p3.owner_hash_value() );
boost::shared_ptr<int> p6( static_cast<int*>(0) );
BOOST_TEST_NE( p4.owner_hash_value(), p6.owner_hash_value() );
boost::shared_ptr<void> p7( p1 );
BOOST_TEST_EQ( p1.owner_hash_value(), p7.owner_hash_value() );
boost::shared_ptr<void> p8;
BOOST_TEST_NE( p1.owner_hash_value(), p8.owner_hash_value() );
BOOST_TEST_EQ( p4.owner_hash_value(), p8.owner_hash_value() );
boost::weak_ptr<int> q1( p1 );
BOOST_TEST_EQ( p1.owner_hash_value(), q1.owner_hash_value() );
boost::weak_ptr<int> q2( p1 );
BOOST_TEST_EQ( q1.owner_hash_value(), q2.owner_hash_value() );
boost::weak_ptr<int> q3( p3 );
BOOST_TEST_NE( p1.owner_hash_value(), q3.owner_hash_value() );
BOOST_TEST_NE( q1.owner_hash_value(), q3.owner_hash_value() );
boost::weak_ptr<int> q4;
BOOST_TEST_EQ( p4.owner_hash_value(), q4.owner_hash_value() );
BOOST_TEST_NE( q1.owner_hash_value(), q4.owner_hash_value() );
boost::weak_ptr<void> q5;
BOOST_TEST_EQ( q4.owner_hash_value(), q5.owner_hash_value() );
boost::weak_ptr<void> q7( p7 );
BOOST_TEST_EQ( p1.owner_hash_value(), q7.owner_hash_value() );
BOOST_TEST_EQ( q1.owner_hash_value(), q7.owner_hash_value() );
p1.reset();
p2.reset();
p3.reset();
p7.reset();
BOOST_TEST( q1.expired() );
BOOST_TEST( q2.expired() );
BOOST_TEST( q3.expired() );
BOOST_TEST( q7.expired() );
BOOST_TEST_EQ( q1.owner_hash_value(), q2.owner_hash_value() );
BOOST_TEST_EQ( q1.owner_hash_value(), q7.owner_hash_value() );
BOOST_TEST_NE( q1.owner_hash_value(), q3.owner_hash_value() );
BOOST_TEST_NE( q1.owner_hash_value(), q4.owner_hash_value() );
}
return boost::report_errors();
}

View File

@@ -0,0 +1,153 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#include <memory>
#include <utility>
#if defined( BOOST_NO_CXX11_SMART_PTR )
BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_NO_CXX11_SMART_PTR is defined")
int main() {}
#elif defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_NO_CXX11_RVALUE_REFERENCES is defined")
int main() {}
#elif defined(BOOST_MSVC) && BOOST_MSVC < 1700
BOOST_PRAGMA_MESSAGE("Skipping test because msvc-10.0 unique_ptr doesn't support move-only deleters")
int main() {}
#else
struct Y
{
static int instances;
bool deleted_;
Y(): deleted_( false )
{
++instances;
}
~Y()
{
BOOST_TEST( deleted_ );
--instances;
}
private:
Y( Y const & );
Y & operator=( Y const & );
};
int Y::instances = 0;
struct YD
{
bool moved_;
YD(): moved_( false )
{
}
YD( YD&& r ): moved_( false )
{
r.moved_ = true;
}
void operator()( Y* p ) const
{
BOOST_TEST( !moved_ );
if( p )
{
p->deleted_ = true;
delete p;
}
else
{
BOOST_ERROR( "YD::operator()(0) called" );
}
}
private:
YD( YD const & );
YD & operator=( YD const & );
};
int main()
{
BOOST_TEST( Y::instances == 0 );
{
std::unique_ptr<Y, YD> p( new Y );
BOOST_TEST( Y::instances == 1 );
boost::shared_ptr<Y> p2( std::move( p ) );
BOOST_TEST( Y::instances == 1 );
BOOST_TEST( p.get() == 0 );
BOOST_TEST( p.get_deleter().moved_ );
p2.reset();
BOOST_TEST( Y::instances == 0 );
}
{
std::unique_ptr<Y, YD> p( new Y );
BOOST_TEST( Y::instances == 1 );
boost::shared_ptr<void> p2( std::move( p ) );
BOOST_TEST( Y::instances == 1 );
BOOST_TEST( p.get() == 0 );
BOOST_TEST( p.get_deleter().moved_ );
p2.reset();
BOOST_TEST( Y::instances == 0 );
}
{
std::unique_ptr<Y, YD> p( new Y );
BOOST_TEST( Y::instances == 1 );
boost::shared_ptr<Y> p2;
p2 = std::move( p );
BOOST_TEST( Y::instances == 1 );
BOOST_TEST( p.get() == 0 );
BOOST_TEST( p.get_deleter().moved_ );
p2.reset();
BOOST_TEST( Y::instances == 0 );
}
{
std::unique_ptr<Y, YD> p( new Y );
BOOST_TEST( Y::instances == 1 );
boost::shared_ptr<void> p2( new int(0) );
p2 = std::move( p );
BOOST_TEST( Y::instances == 1 );
BOOST_TEST( p.get() == 0 );
BOOST_TEST( p.get_deleter().moved_ );
p2.reset();
BOOST_TEST( Y::instances == 0 );
}
return boost::report_errors();
}
#endif

View File

@@ -0,0 +1,51 @@
// Copyright 2011, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/owner_hash.hpp>
#include <boost/smart_ptr/owner_equal_to.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#if defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
int main() {}
#else
#include <unordered_set>
int main()
{
std::unordered_set< boost::shared_ptr<void>, boost::owner_hash< boost::shared_ptr<void> >, boost::owner_equal_to< boost::shared_ptr<void> > > set;
boost::shared_ptr<int> p1( (int*)0 );
boost::shared_ptr<int> p2( p1 );
boost::shared_ptr<void> p3( p1 );
set.insert( p1 );
set.insert( p2 );
set.insert( p3 );
BOOST_TEST_EQ( set.size(), 1 );
boost::shared_ptr<int> p4( (int*)0 );
set.insert( p4 );
BOOST_TEST_EQ( set.size(), 2 );
BOOST_TEST_EQ( set.count( p1 ), 1 );
BOOST_TEST_EQ( set.count( p2 ), 1 );
BOOST_TEST_EQ( set.count( p3 ), 1 );
BOOST_TEST_EQ( set.count( p4 ), 1 );
boost::shared_ptr<int> p5( (int*)0 );
BOOST_TEST_EQ( set.count( p5 ), 0 );
return boost::report_errors();
}
#endif // #if defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)

76
test/wp_hash_test.cpp Normal file
View File

@@ -0,0 +1,76 @@
// Copyright 2011, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/weak_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/functional/hash.hpp>
#include <boost/core/lightweight_test.hpp>
int main()
{
{
boost::hash< boost::weak_ptr<int> > hasher;
boost::shared_ptr<int> p1, p2( p1 ), p3( new int ), p4( p3 ), p5( new int );
boost::weak_ptr<int> q1( p1 ), q2( p2 ), q3( p3 ), q4( p4 ), q5( p5 );
BOOST_TEST_EQ( hasher( q1 ), hasher( q2 ) );
BOOST_TEST_NE( hasher( q1 ), hasher( q3 ) );
BOOST_TEST_EQ( hasher( q3 ), hasher( q4 ) );
BOOST_TEST_NE( hasher( q3 ), hasher( q5 ) );
p3.reset();
p4.reset();
p5.reset();
BOOST_TEST_EQ( hasher( q1 ), hasher( q2 ) );
BOOST_TEST_NE( hasher( q1 ), hasher( q3 ) );
BOOST_TEST_EQ( hasher( q3 ), hasher( q4 ) );
BOOST_TEST_NE( hasher( q3 ), hasher( q5 ) );
}
{
boost::hash< boost::weak_ptr<int[]> > hasher;
boost::shared_ptr<int[]> p1, p2( p1 ), p3( new int[1] ), p4( p3 ), p5( new int[1] );
boost::weak_ptr<int[]> q1( p1 ), q2( p2 ), q3( p3 ), q4( p4 ), q5( p5 );
BOOST_TEST_EQ( hasher( q1 ), hasher( q2 ) );
BOOST_TEST_NE( hasher( q1 ), hasher( q3 ) );
BOOST_TEST_EQ( hasher( q3 ), hasher( q4 ) );
BOOST_TEST_NE( hasher( q3 ), hasher( q5 ) );
p3.reset();
p4.reset();
p5.reset();
BOOST_TEST_EQ( hasher( q1 ), hasher( q2 ) );
BOOST_TEST_NE( hasher( q1 ), hasher( q3 ) );
BOOST_TEST_EQ( hasher( q3 ), hasher( q4 ) );
BOOST_TEST_NE( hasher( q3 ), hasher( q5 ) );
}
{
boost::hash< boost::weak_ptr<int[1]> > hasher;
boost::shared_ptr<int[1]> p1, p2( p1 ), p3( new int[1] ), p4( p3 ), p5( new int[1] );
boost::weak_ptr<int[1]> q1( p1 ), q2( p2 ), q3( p3 ), q4( p4 ), q5( p5 );
BOOST_TEST_EQ( hasher( q1 ), hasher( q2 ) );
BOOST_TEST_NE( hasher( q1 ), hasher( q3 ) );
BOOST_TEST_EQ( hasher( q3 ), hasher( q4 ) );
BOOST_TEST_NE( hasher( q3 ), hasher( q5 ) );
p3.reset();
p4.reset();
p5.reset();
BOOST_TEST_EQ( hasher( q1 ), hasher( q2 ) );
BOOST_TEST_NE( hasher( q1 ), hasher( q3 ) );
BOOST_TEST_EQ( hasher( q3 ), hasher( q4 ) );
BOOST_TEST_NE( hasher( q3 ), hasher( q5 ) );
}
return boost::report_errors();
}

61
test/wp_hash_test2.cpp Normal file
View File

@@ -0,0 +1,61 @@
// Copyright 2011, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/weak_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <functional>
#if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
int main() {}
#else
int main()
{
{
boost::shared_ptr<int> p1, p2( new int );
boost::weak_ptr<int> q1( p1 ), q2( p2 ), q3;
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int> >()( q1 ), q1.owner_hash_value() );
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int> >()( q2 ), q2.owner_hash_value() );
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int> >()( q3 ), q3.owner_hash_value() );
p2.reset();
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int> >()( q2 ), q2.owner_hash_value() );
}
{
boost::shared_ptr<int[]> p1, p2( new int[1] );
boost::weak_ptr<int[]> q1( p1 ), q2( p2 ), q3;
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int[]> >()( q1 ), q1.owner_hash_value() );
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int[]> >()( q2 ), q2.owner_hash_value() );
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int[]> >()( q3 ), q3.owner_hash_value() );
p2.reset();
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int[]> >()( q2 ), q2.owner_hash_value() );
}
{
boost::shared_ptr<int[1]> p1, p2( new int[1] );
boost::weak_ptr<int[1]> q1( p1 ), q2( p2 ), q3;
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int[1]> >()( q1 ), q1.owner_hash_value() );
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int[1]> >()( q2 ), q2.owner_hash_value() );
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int[1]> >()( q3 ), q3.owner_hash_value() );
p2.reset();
BOOST_TEST_EQ( std::hash< boost::weak_ptr<int[1]> >()( q2 ), q2.owner_hash_value() );
}
return boost::report_errors();
}
#endif // #if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)

View File

@@ -0,0 +1,87 @@
// Copyright 2011, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/weak_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#if defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)
int main() {}
#else
#include <unordered_set>
int main()
{
std::unordered_set< boost::weak_ptr<void> > set;
boost::shared_ptr<int> p1( (int*)0 );
boost::shared_ptr<int> p2( p1 );
boost::shared_ptr<void> p3( p1 );
set.insert( p1 );
set.insert( p2 );
set.insert( p3 );
BOOST_TEST_EQ( set.size(), 1 );
boost::weak_ptr<int> q1( p1 );
boost::weak_ptr<int> q2( p2 );
boost::weak_ptr<void> q3( p3 );
boost::weak_ptr<int> q4( q2 );
boost::weak_ptr<void> q5( q3 );
set.insert( q1 );
set.insert( q2 );
set.insert( q3 );
set.insert( q4 );
set.insert( q5 );
BOOST_TEST_EQ( set.size(), 1 );
boost::shared_ptr<int> p6( (int*)0 );
set.insert( p6 );
BOOST_TEST_EQ( set.size(), 2 );
boost::weak_ptr<int> q6( p6 );
set.insert( q6 );
BOOST_TEST_EQ( set.size(), 2 );
BOOST_TEST_EQ( set.count( q1 ), 1 );
BOOST_TEST_EQ( set.count( q2 ), 1 );
BOOST_TEST_EQ( set.count( q3 ), 1 );
BOOST_TEST_EQ( set.count( q4 ), 1 );
BOOST_TEST_EQ( set.count( q5 ), 1 );
BOOST_TEST_EQ( set.count( q6 ), 1 );
boost::shared_ptr<int> p7( (int*)0 );
boost::weak_ptr<int> q7( p7 );
BOOST_TEST_EQ( set.count( q7 ), 0 );
p1.reset();
p2.reset();
p3.reset();
p6.reset();
p7.reset();
BOOST_TEST_EQ( set.count( q1 ), 1 );
BOOST_TEST_EQ( set.count( q2 ), 1 );
BOOST_TEST_EQ( set.count( q3 ), 1 );
BOOST_TEST_EQ( set.count( q4 ), 1 );
BOOST_TEST_EQ( set.count( q5 ), 1 );
BOOST_TEST_EQ( set.count( q6 ), 1 );
BOOST_TEST_EQ( set.count( q7 ), 0 );
return boost::report_errors();
}
#endif // #if defined(BOOST_NO_CXX11_HDR_UNORDERED_SET)