Compare commits

..

67 Commits

Author SHA1 Message Date
Peter Dimov
b6b49ef591 Split g++ 8 Travis job, because log length 2019-04-22 02:19:27 +03:00
Peter Dimov
2122c7753c Avoid memcpy over a spinlock, because g++ 8 warns 2019-04-22 02:17:28 +03:00
Peter Dimov
7c76fb385d Add clang-win to Appveyor 2019-04-22 00:59:38 +03:00
Peter Dimov
372fac679b Remove _internal_aliasing_assign 2019-04-21 23:13:06 +03:00
Peter Dimov
e3adcaed1e Add revision history 2019-04-21 23:00:24 +03:00
Peter Dimov
016e682af6 Document weak_ptr aliasing constructors and empty 2019-04-21 22:52:44 +03:00
Peter Dimov
78e095d761 Disable tests that don't compile on msvc-8.0 2019-04-21 22:50:24 +03:00
Peter Dimov
eb8a91cb46 Add tests for the weak_ptr aliasing constructors 2019-04-21 22:44:09 +03:00
Peter Dimov
513cd15378 Add aliasing constructors to weak_ptr. Closes #67. 2019-04-21 22:43:04 +03:00
Peter Dimov
7bfa6a1f3d Fix typo 2019-04-21 21:33:55 +03:00
Peter Dimov
8120bb44cb Add rvalue pointer casts (closes #66) 2019-04-21 00:47:36 +03:00
Peter Dimov
18974ea2db Add cast tests to intrusive_ptr_test 2019-04-20 18:54:13 +03:00
Peter Dimov
2a4aca403a Merge branch 'develop' into feature/intrusive-ptr-tests 2019-04-20 18:15:31 +03:00
Peter Dimov
4d0d81477c Update msvc workarounds for 14.2 2019-04-20 18:15:05 +03:00
Peter Dimov
1725e26f70 Add assignment tests to intrusive_ptr_test 2019-04-20 18:02:11 +03:00
Peter Dimov
47fffaf11c Switch Appveyor to 2015 image 2019-04-14 18:24:21 +03:00
Peter Dimov
7f0323a347 Merge branch 'develop' of https://github.com/boostorg/smart_ptr into develop 2019-03-25 19:25:44 +02:00
Peter Dimov
6d8ea0f0c4 Remove project-id from doc/Jamfile 2019-03-25 19:25:33 +02:00
Glen Fernandes
d10299159a More asciidoctor changes
Reinstate the none/blank trick, but remove the blank line after it in local_shared_ptr.adoc that causes the problem. Also use that trick in place of the nested DLs which don't work with Asciidoctor 2
2019-03-24 23:41:08 -04:00
Glen Fernandes
adcab0e313 Update asciidoc to work with Asciidoctor 2.0 2019-03-24 20:28:17 -04:00
Peter Dimov
4fbb9ff076 Merge branch 'develop' 2019-03-02 21:08:43 +02:00
Glen Fernandes
8ccb36dfcf Use traits from TypeTraits 2019-02-22 19:36:32 -05:00
Glen Fernandes
fde2e91443 Use traits from TypeTraits 2019-02-22 19:01:55 -05:00
Peter Dimov
aa1341a6a2 Add BOOST_SP_NOEXCEPT to sp_counted_base_nt.hpp 2019-01-28 21:24:09 +02:00
Peter Dimov
053779f3ee Add BOOST_SP_NOEXCEPT to sp_counted_base_clang.hpp 2019-01-28 20:52:28 +02:00
Peter Dimov
51d8167fbf Add more BOOST_SP_NOEXCEPT 2019-01-28 18:46:39 +02:00
Peter Dimov
5f95fe9848 Fix .travis.yml 2019-01-06 04:37:59 +02:00
Peter Dimov
599d0bbba9 Add test/cmake_subdir_test 2019-01-05 19:43:22 +02:00
Peter Dimov
f769217ca8 Update CMakeLists.txt 2019-01-04 19:40:30 +02:00
Mike Dev
5d5d28a92e [CMake] Generate cmake target that other libraries can use
... to express their dependency on this library and retrieve any
configuration information such as the include directory and
transitive dependencies.
2019-01-02 22:32:38 +01:00
Peter Dimov
85fd341402 Merge pull request #59 from Kojoley/patch-1
Do not include the whole Predef for a single macro
2018-12-29 02:24:02 +02:00
Nikita Kniazev
eac6411867 Do not include the whole Predef for a single macro 2018-12-28 03:03:02 +03:00
Peter Dimov
97ef7970e8 Remove VARIANT from .travis.yml 2018-12-23 16:44:03 +02:00
Peter Dimov
4baa21dd5e Add libstdc++-5 for clang 7-ubsan 2018-12-23 08:17:32 +02:00
Peter Dimov
d0a89a81f0 More g++ warning suppression 2018-12-23 06:21:55 +02:00
Peter Dimov
ab2b977e4a Update clang-5 ubsan to clang-7 2018-12-23 05:19:07 +02:00
Peter Dimov
f380d4466c Avoid some g++ warnings in shared_ptr_test 2018-12-23 05:06:24 +02:00
Peter Dimov
2932ca4203 Change sp_counted_base_nt/_pt to use boost::int_least32_t instead of long (which may be 64 bit) 2018-12-23 01:54:36 +02:00
Peter Dimov
660d26c2c3 Change 03/11 to 98/0x for gcc 4.4 2018-12-23 00:08:32 +02:00
Peter Dimov
a095084492 Improve abi_test 2018-12-23 00:06:13 +02:00
Peter Dimov
a314765b94 Test variant=debug,release on Travis 2018-12-22 23:52:07 +02:00
Peter Dimov
02eba55685 Add abi_test 2018-12-22 22:56:20 +02:00
Peter Dimov
9c2c991291 Update .yml files 2018-12-18 21:53:58 +02:00
Peter Dimov
2e57ddb953 Update documentation of intrusive_ptr (document move ops, fix op<) 2018-11-25 17:54:51 +02:00
Peter Dimov
f6c3508aee Add make_local_shared_const_test 2018-11-10 21:04:22 +02:00
Peter Dimov
b7cca00408 Add make_shared_const_test 2018-11-10 20:44:00 +02:00
Peter Dimov
7e50abb9ec Merge pull request #55 from Romain-Geissler-1A/noexcept
Use BOOST_NOEXCEPT_OR_NOTHROW in public headers to prepare for C++20.
2018-11-10 19:32:01 +02:00
Peter Dimov
e7360779b0 Add g++ 8, clang 6.0, 7 to Travis 2018-11-10 18:35:29 +02:00
Romain Geissler
456da93897 Use BOOST_NOEXCEPT_OR_NOTHROW in public headers to prepare for C++20. 2018-11-09 14:55:34 +00:00
Peter Dimov
04f0847af4 Add --depth 1 to Appveyor 2018-09-21 20:53:27 +03:00
Glen Fernandes
29a08cdff6 Use BOOST_SYMBOL_VISIBLE with local_counted_base and children 2018-09-19 13:50:13 -04:00
Peter Dimov
6d3af760f6 Generously dispense BOOST_SYMBOL_VISIBLE 2018-09-18 03:18:23 +03:00
Peter Dimov
a9f39d2b94 Test make_shared/allocate_shared in dll_test too 2018-09-17 22:04:27 +03:00
Peter Dimov
4e2f236116 Add dll_test (to check for visibility issues) 2018-09-17 21:50:47 +03:00
Peter Dimov
4eb53db537 Use intrin.h under clang-cl 2018-08-12 01:26:59 +03:00
Glen Fernandes
a2b6ba85f3 Simplify exception safety in array construct utilities 2018-08-01 08:45:10 -04:00
Peter Dimov
e37cd4154f Work around ld: unrecognized option '--push-state--no-as-needed' 2018-05-10 16:16:08 +03:00
Peter Dimov
8563fc5c4e Add tests that include <windows.h> 2018-03-11 23:00:50 +02:00
Peter Dimov
67fab5c9ec Clang x64 warns that __stdcall is ignored, so don't use it there 2018-03-08 06:53:28 +02:00
Peter Dimov
f16fbdce26 Fix sp_interlocked on Cygwin 64 2018-03-08 05:15:49 +02:00
Peter Dimov
c3b3835a58 Mingw doesn't have _RTL_CRITICAL_SECTION 2018-03-08 03:34:00 +02:00
Peter Dimov
d1600b8abc Do not define pthread_* in lightweight_thread.hpp; mingw-w64 includes pthread.h in the standard library headers 2018-03-08 01:19:44 +02:00
Peter Dimov
5885763287 Remove clang from Appveyor; doesn't really work. 2018-03-08 00:39:15 +02:00
Peter Dimov
9bb12692b3 Only test C++14 with clang on Appveyor 2018-03-07 21:23:01 +02:00
Peter Dimov
773ef80f5d Add mingw configurations; move LLVM clang in its own VS2017 job 2018-03-07 20:06:04 +02:00
Peter Dimov
704de2bd67 Add Cygwin to Appveyor 2018-03-07 18:27:45 +02:00
Peter Dimov
1caa233faa Add address-model=32,64 to Appveyor 2018-03-07 17:37:28 +02:00
81 changed files with 2477 additions and 775 deletions

View File

@@ -1,4 +1,4 @@
# Copyright 2016, 2017, 2018 Peter Dimov # Copyright 2016-2019 Peter Dimov
# Distributed under the Boost Software License, Version 1.0. # 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) # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
@@ -24,7 +24,7 @@ matrix:
include: include:
- os: linux - os: linux
compiler: g++ compiler: g++
env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11 VARIANT=debug,release env: TOOLSET=gcc COMPILER=g++ CXXSTD=03,11
- os: linux - os: linux
compiler: g++-4.4 compiler: g++-4.4
@@ -97,7 +97,7 @@ matrix:
- os: linux - os: linux
compiler: g++-7 compiler: g++-7
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 VARIANT=release env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17
addons: addons:
apt: apt:
packages: packages:
@@ -105,9 +105,29 @@ matrix:
sources: sources:
- ubuntu-toolchain-r-test - 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 - os: linux
compiler: g++-7 compiler: g++-7
env: UBSAN=1 TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 UBSAN_OPTIONS=print_stacktrace=1 env: UBSAN=1 TOOLSET=gcc COMPILER=g++-7 CXXSTD=03,11,14,17 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
addons: addons:
apt: apt:
packages: packages:
@@ -117,7 +137,7 @@ matrix:
- os: linux - os: linux
compiler: clang++ compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11 VARIANT=debug,release env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11
- os: linux - os: linux
compiler: /usr/bin/clang++ compiler: /usr/bin/clang++
@@ -206,7 +226,7 @@ matrix:
- os: linux - os: linux
compiler: clang++-5.0 compiler: clang++-5.0
env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z VARIANT=release env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z
addons: addons:
apt: apt:
packages: packages:
@@ -216,19 +236,42 @@ matrix:
- llvm-toolchain-trusty-5.0 - llvm-toolchain-trusty-5.0
- os: linux - os: linux
compiler: clang++-5.0 compiler: clang++-6.0
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=03,11,14,1z UBSAN_OPTIONS=print_stacktrace=1 env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=03,11,14,17,2a
addons: addons:
apt: apt:
packages: packages:
- clang-5.0 - clang-6.0
sources: sources:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-trusty-5.0 - llvm-toolchain-trusty-6.0
- os: linux
compiler: clang++-7
env: TOOLSET=clang COMPILER=clang++-7 CXXSTD=03,11,14,17,2a
addons:
apt:
packages:
- clang-7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7
- os: linux
compiler: clang++-7
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-7 CXXSTD=03,11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
- clang-7
- libstdc++-5-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-7
- os: linux - os: linux
compiler: clang++-libc++ compiler: clang++-libc++
env: TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z VARIANT=release env: TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=03,11,14,1z
addons: addons:
apt: apt:
packages: packages:
@@ -246,6 +289,15 @@ matrix:
compiler: clang++ compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
- os: linux
compiler: g++
env: CMAKE_SUBDIR_TEST=1
script:
- cd libs/smart_ptr/test/cmake_subdir_test && mkdir __build__ && cd __build__
- cmake ..
- cmake --build .
- cmake --build . --target check
install: install:
- BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
- cd .. - cd ..
@@ -265,7 +317,9 @@ install:
- git submodule init libs/detail - git submodule init libs/detail
- git submodule init libs/integer - git submodule init libs/integer
- git submodule init tools/build - git submodule init tools/build
- git submodule update - git submodule init libs/headers
- git submodule init tools/boost_install
- git submodule update --jobs 3
- cp -r $TRAVIS_BUILD_DIR/* libs/smart_ptr - cp -r $TRAVIS_BUILD_DIR/* libs/smart_ptr
- ./bootstrap.sh - ./bootstrap.sh
- ./b2 headers - ./b2 headers
@@ -273,7 +327,7 @@ install:
script: script:
- |- - |-
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
- ./b2 -j3 libs/smart_ptr/test toolset=$TOOLSET cxxstd=$CXXSTD ${VARIANT:+variant=$VARIANT} ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} - ./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: notifications:
email: email:

26
CMakeLists.txt Normal file
View File

@@ -0,0 +1,26 @@
# Copyright 2018 Mike Dev
# Distributed under the Boost Software License, Version 1.0.
# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
# Partial (add_subdirectory only) and experimental CMake support
# Subject to change; please do not rely on the contents of this file yet
cmake_minimum_required(VERSION 3.5)
project(BoostSmartPtr LANGUAGES CXX)
add_library(boost_smart_ptr INTERFACE)
add_library(Boost::smart_ptr ALIAS boost_smart_ptr)
target_include_directories(boost_smart_ptr INTERFACE include)
target_link_libraries(boost_smart_ptr
INTERFACE
Boost::assert
Boost::config
Boost::core
Boost::move
Boost::predef
Boost::static_assert
Boost::throw_exception
Boost::type_traits
)

View File

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

View File

@@ -5,8 +5,6 @@
# See accompanying file LICENSE_1_0.txt or copy at # See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt # http://www.boost.org/LICENSE_1_0.txt
project doc/smart_ptr ;
import asciidoctor ; import asciidoctor ;
html smart_ptr.html : smart_ptr.adoc ; html smart_ptr.html : smart_ptr.adoc ;

View File

@@ -19,6 +19,8 @@ Greg Colvin, Beman Dawes, Peter Dimov, Glen Fernandes
include::smart_ptr/introduction.adoc[] include::smart_ptr/introduction.adoc[]
include::smart_ptr/changelog.adoc[]
include::smart_ptr/scoped_ptr.adoc[] include::smart_ptr/scoped_ptr.adoc[]
include::smart_ptr/scoped_array.adoc[] include::smart_ptr/scoped_array.adoc[]

View File

@@ -0,0 +1,19 @@
////
Copyright 2019 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt
////
[#changelog]
# Revision History
:toc:
:toc-title:
:idprefix: changelog_
## Changes in 1.71.0
* Added aliasing constructors to `weak_ptr`
* Added `weak_ptr<T>::empty()`

View File

@@ -11,7 +11,9 @@ http://www.boost.org/LICENSE_1_0.txt
[#introduction] [#introduction]
# Introduction # Introduction
:idprefix: intro :toc:
:toc-title:
:idprefix: intro_
Smart pointers are objects which store pointers to dynamically allocated (heap) objects. 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 They behave much like built-in {cpp} pointers except that they automatically delete the object

View File

@@ -54,12 +54,18 @@ namespace boost {
intrusive_ptr(intrusive_ptr const & r); intrusive_ptr(intrusive_ptr const & r);
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r); template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
intrusive_ptr(intrusive_ptr && r);
template<class Y> intrusive_ptr(intrusive_ptr<Y> && r);
~intrusive_ptr(); ~intrusive_ptr();
intrusive_ptr & operator=(intrusive_ptr const & r); intrusive_ptr & operator=(intrusive_ptr const & r);
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r); template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
intrusive_ptr & operator=(T * r); intrusive_ptr & operator=(T * r);
intrusive_ptr & operator=(intrusive_ptr && r);
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r);
void reset(); void reset();
void reset(T * r); void reset(T * r);
void reset(T * r, bool add_ref); void reset(T * r, bool add_ref);
@@ -71,7 +77,7 @@ namespace boost {
explicit operator bool () const noexcept; explicit operator bool () const noexcept;
void swap(intrusive_ptr & b) noexept; void swap(intrusive_ptr & b) noexcept;
}; };
template<class T, class U> template<class T, class U>
@@ -92,8 +98,8 @@ namespace boost {
template<class T, class U> template<class T, class U>
bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept; bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;
template<class T, class U> template<class T>
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept; bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept;
template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept; template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;
@@ -158,6 +164,18 @@ template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
Effects:: `T * p = r.get(); if(p != 0) intrusive_ptr_add_ref(p);`. Effects:: `T * p = r.get(); if(p != 0) intrusive_ptr_add_ref(p);`.
Postconditions:: `get() == r.get()`. Postconditions:: `get() == r.get()`.
```
intrusive_ptr(intrusive_ptr && r);
```
```
template<class Y> intrusive_ptr(intrusive_ptr<Y> && r);
```
[none]
* {blank}
+
Postconditions:: `get()` equals the old value of `r.get()`. `r.get() == 0`.
### destructor ### destructor
``` ```
@@ -187,6 +205,19 @@ intrusive_ptr & operator=(T * r);
Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`. Effects:: Equivalent to `intrusive_ptr(r).swap(*this)`.
Returns:: `*this`. Returns:: `*this`.
```
intrusive_ptr & operator=(intrusive_ptr && r);
```
```
template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> && r);
```
[none]
* {blank}
+
Effects:: Equivalent to `intrusive_ptr(std::move(r)).swap(*this)`.
Returns:: `*this`.
### reset ### reset
``` ```
@@ -361,8 +392,8 @@ template<class T, class U>
Returns:: `a != b.get()`. Returns:: `a != b.get()`.
``` ```
template<class T, class U> template<class T>
bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept; bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept;
``` ```
[none] [none]

View File

@@ -78,12 +78,13 @@ namespace boost {
``` ```
intrusive_ref_counter() noexcept; intrusive_ref_counter() noexcept;
``` ```
::
``` ```
intrusive_ref_counter(const intrusive_ref_counter&) noexcept; intrusive_ref_counter(const intrusive_ref_counter&) noexcept;
``` ```
:: [none]
Postconditions::: `use_count() == 0`. * {blank}
+
Postconditions:: `use_count() == 0`.
NOTE: The pointer to the constructed object is expected to be passed to NOTE: The pointer to the constructed object is expected to be passed to
`intrusive_ptr` constructor, assignment operator or `reset` method, which `intrusive_ptr` constructor, assignment operator or `reset` method, which
@@ -94,8 +95,10 @@ would increment the reference counter.
``` ```
~intrusive_ref_counter(); ~intrusive_ref_counter();
``` ```
:: [none]
Effects::: Destroys the counter object. * {blank}
+
Effects:: Destroys the counter object.
NOTE: The destructor is protected so that the object can only be destroyed NOTE: The destructor is protected so that the object can only be destroyed
through the `Derived` class. through the `Derived` class.
@@ -105,16 +108,20 @@ through the `Derived` class.
``` ```
intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept; intrusive_ref_counter& operator=(const intrusive_ref_counter& v) noexcept;
``` ```
:: [none]
Effects::: Does nothing, reference counter is not modified. * {blank}
+
Effects:: Does nothing, reference counter is not modified.
### use_count ### use_count
``` ```
unsigned int use_count() const noexcept; unsigned int use_count() const noexcept;
``` ```
:: [none]
Returns::: The current value of the reference counter. * {blank}
+
Returns:: The current value of the reference counter.
NOTE: The returned value may not be actual in multi-threaded applications. NOTE: The returned value may not be actual in multi-threaded applications.
@@ -127,8 +134,10 @@ template<class Derived, class CounterPolicy>
void intrusive_ptr_add_ref( void intrusive_ptr_add_ref(
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept; const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
``` ```
:: [none]
Effects::: Increments the reference counter. * {blank}
+
Effects:: Increments the reference counter.
### intrusive_ptr_release ### intrusive_ptr_release
@@ -137,6 +146,8 @@ template<class Derived, class CounterPolicy>
void intrusive_ptr_release( void intrusive_ptr_release(
const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept; const intrusive_ref_counter<Derived, CounterPolicy>* p) noexcept;
``` ```
:: [none]
Effects::: Decrements the reference counter. If the reference counter reaches * {blank}
+
Effects:: Decrements the reference counter. If the reference counter reaches
0, calls `delete static_cast<const Derived*>(p)`. 0, calls `delete static_cast<const Derived*>(p)`.

View File

@@ -716,4 +716,3 @@ template<class D, class T>
* {blank} * {blank}
+ +
Returns:: If `*this` owns a `shared_ptr` instance `p`, `get_deleter<D>( p )`, otherwise 0. Returns:: If `*this` owns a `shared_ptr` instance `p`, `get_deleter<D>( p )`, otherwise 0.

View File

@@ -174,17 +174,18 @@ the reference counts.
template<class T, class... Args> template<class T, class... Args>
shared_ptr<T> make_shared(Args&&... args); shared_ptr<T> make_shared(Args&&... args);
``` ```
::
``` ```
template<class T, class A, class... Args> template<class T, class A, class... Args>
shared_ptr<T> allocate_shared(const A& a, Args&&... args); shared_ptr<T> allocate_shared(const A& a, Args&&... args);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is not an array type. `T` is not an array type.
Returns::: A `shared_ptr` to an object of type `T`, constructed from Returns:: A `shared_ptr` to an object of type `T`, constructed from
`args\...`. `args\...`.
Examples::: Examples::
* `auto p = make_shared<int>();` * `auto p = make_shared<int>();`
* `auto p = make_shared<std::vector<int> >(16, 1);` * `auto p = make_shared<std::vector<int> >(16, 1);`
@@ -192,17 +193,18 @@ Examples:::
template<class T> template<class T>
shared_ptr<T> make_shared(std::size_t n); shared_ptr<T> make_shared(std::size_t n);
``` ```
::
``` ```
template<class T, class A> template<class T, class A>
shared_ptr<T> allocate_shared(const A& a, std::size_t n); shared_ptr<T> allocate_shared(const A& a, std::size_t n);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[]`. `T` is an array type of the form `U[]`.
Returns::: A `shared_ptr` to a sequence of `n` value-initialized objects of Returns:: A `shared_ptr` to a sequence of `n` value-initialized objects of
type `U`. type `U`.
Examples::: Examples::
* `auto p = make_shared<double[]>(1024);` * `auto p = make_shared<double[]>(1024);`
* `auto p = make_shared<double[][2][2]>(6);` * `auto p = make_shared<double[][2][2]>(6);`
@@ -210,17 +212,18 @@ Examples:::
template<class T> template<class T>
shared_ptr<T> make_shared(); shared_ptr<T> make_shared();
``` ```
::
``` ```
template<class T, class A> template<class T, class A>
shared_ptr<T> allocate_shared(const A& a); shared_ptr<T> allocate_shared(const A& a);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[N]`. `T` is an array type of the form `U[N]`.
Returns::: A `shared_ptr` to a sequence of `N` value-initialized objects of Returns:: A `shared_ptr` to a sequence of `N` value-initialized objects of
type `U`. type `U`.
Examples::: Examples::
* `auto p = make_shared<double[1024]>();` * `auto p = make_shared<double[1024]>();`
* `auto p = make_shared<double[6][2][2]>();` * `auto p = make_shared<double[6][2][2]>();`
@@ -228,17 +231,18 @@ Examples:::
template<class T> shared_ptr<T> template<class T> shared_ptr<T>
make_shared(std::size_t n, const remove_extent_t<T>& v); make_shared(std::size_t n, const remove_extent_t<T>& v);
``` ```
::
``` ```
template<class T, class A> shared_ptr<T> template<class T, class A> shared_ptr<T>
allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v); allocate_shared(const A& a, std::size_t n, const remove_extent_t<T>& v);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[]`. `T` is an array type of the form `U[]`.
Returns::: A `shared_ptr` to a sequence of `n` objects of type `U`, each Returns:: A `shared_ptr` to a sequence of `n` objects of type `U`, each
initialized to `v`. initialized to `v`.
Examples::: Examples::
* `auto p = make_shared<double[]>(1024, 1.0);` * `auto p = make_shared<double[]>(1024, 1.0);`
* `auto p = make_shared<double[][2]>(6, {1.0, 0.0});` * `auto p = make_shared<double[][2]>(6, {1.0, 0.0});`
* `auto p = make_shared<std::vector<int>[]>(4, {1, 2});` * `auto p = make_shared<std::vector<int>[]>(4, {1, 2});`
@@ -247,17 +251,18 @@ Examples:::
template<class T> template<class T>
shared_ptr<T> make_shared(const remove_extent_t<T>& v); shared_ptr<T> make_shared(const remove_extent_t<T>& v);
``` ```
::
``` ```
template<class T, class A> template<class T, class A>
shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v); shared_ptr<T> allocate_shared(const A& a, const remove_extent_t<T>& v);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[N]`. `T` is an array type of the form `U[N]`.
Returns::: A `shared_ptr` to a sequence of `N` objects of type `U`, each Returns:: A `shared_ptr` to a sequence of `N` objects of type `U`, each
initialized to `v`. initialized to `v`.
Examples::: Examples::
* `auto p = make_shared<double[1024]>(1.0);` * `auto p = make_shared<double[1024]>(1.0);`
* `auto p = make_shared<double[6][2]>({1.0, 0.0});` * `auto p = make_shared<double[6][2]>({1.0, 0.0});`
* `auto p = make_shared<std::vector<int>[4]>({1, 2});` * `auto p = make_shared<std::vector<int>[4]>({1, 2});`
@@ -266,30 +271,32 @@ Examples:::
template<class T> template<class T>
shared_ptr<T> make_shared_noinit(); shared_ptr<T> make_shared_noinit();
``` ```
::
``` ```
template<class T, class A> template<class T, class A>
shared_ptr<T> allocate_shared_noinit(const A& a); shared_ptr<T> allocate_shared_noinit(const A& a);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is not an array type, or an array type of the `U[N]`. `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 Returns:: A `shared_ptr` to a default-initialized object of type `T`, or a
sequence of `N` default-initialized objects of type `U`, respectively. sequence of `N` default-initialized objects of type `U`, respectively.
Example::: `auto p = make_shared_noinit<double[1024]>();` Example:: `auto p = make_shared_noinit<double[1024]>();`
``` ```
template<class T> template<class T>
shared_ptr<T> make_shared_noinit(std::size_t n); shared_ptr<T> make_shared_noinit(std::size_t n);
``` ```
::
``` ```
template<class T, class A> template<class T, class A>
shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n); shared_ptr<T> allocate_shared_noinit(const A& a, std::size_t n);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[]`. `T` is an array type of the form `U[]`.
Returns::: A `shared_ptr` to a sequence of `_n_` default-initialized objects Returns:: A `shared_ptr` to a sequence of `_n_` default-initialized objects
of type `U`. of type `U`.
Example::: `auto p = make_shared_noinit<double[]>(1024);` Example:: `auto p = make_shared_noinit<double[]>(1024);`

View File

@@ -68,48 +68,58 @@ namespace boost {
template<class T, class... Args> template<class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args); std::unique_ptr<T> make_unique(Args&&... args);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is not an array type. `T` is not an array type.
Returns::: `std::unique_ptr<T>(new T(std::forward<Args>(args)\...)`. Returns:: `std::unique_ptr<T>(new T(std::forward<Args>(args)\...)`.
Example::: `auto p = make_unique<int>();` Example:: `auto p = make_unique<int>();`
``` ```
template<class T> template<class T>
std::unique_ptr<T> make_unique(remove_reference_t<T>&& v); std::unique_ptr<T> make_unique(remove_reference_t<T>&& v);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is not an array type. `T` is not an array type.
Returns::: `std::unique_ptr<T>(new T(std::move(v))`. Returns:: `std::unique_ptr<T>(new T(std::move(v))`.
Example::: `auto p = make_unique<std::vector<int> >({1, 2});` Example:: `auto p = make_unique<std::vector<int> >({1, 2});`
``` ```
template<class T> template<class T>
std::unique_ptr<T> make_unique(std::size_t n); std::unique_ptr<T> make_unique(std::size_t n);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[]`. `T` is an array type of the form `U[]`.
Returns::: `std::unique_ptr<U[]>(new U[n]())`. Returns:: `std::unique_ptr<U[]>(new U[n]())`.
Example::: `auto p = make_unique<double[]>(1024);` Example:: `auto p = make_unique<double[]>(1024);`
``` ```
template<class T> template<class T>
std::unique_ptr<T> make_unique_noinit(); std::unique_ptr<T> make_unique_noinit();
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is not an array type. `T` is not an array type.
Returns::: `std::unique_ptr<T>(new T)`. Returns:: `std::unique_ptr<T>(new T)`.
Example::: `auto p = make_unique_noinit<double[1024]>();` Example:: `auto p = make_unique_noinit<double[1024]>();`
``` ```
template<class T> template<class T>
std::unique_ptr<T> make_unique_noinit(std::size_t n); std::unique_ptr<T> make_unique_noinit(std::size_t n);
``` ```
:: [none]
Remarks::: These overloads shall only participate in overload resolution when * {blank}
+
Remarks:: These overloads shall only participate in overload resolution when
`T` is an array type of the form `U[]`. `T` is an array type of the form `U[]`.
Returns::: `std::unique_ptr<U[]>(new U[n])`. Returns:: `std::unique_ptr<U[]>(new U[n])`.
Example::: `auto p = make_unique_noinit<double[]>(1024);` Example:: `auto p = make_unique_noinit<double[]>(1024);`

View File

@@ -78,23 +78,29 @@ namespace boost {
``` ```
template<class T, class U> T* static_pointer_cast(U* p) noexcept; template<class T, class U> T* static_pointer_cast(U* p) noexcept;
``` ```
:: [none]
Returns::: `static_cast<T*>(p)` * {blank}
+
Returns:: `static_cast<T*>(p)`
``` ```
template<class T, class U> std::shared_ptr<T> template<class T, class U> std::shared_ptr<T>
static_pointer_cast(const std::shared_ptr<U>& p) noexcept; static_pointer_cast(const std::shared_ptr<U>& p) noexcept;
``` ```
:: [none]
Returns::: `std::static_pointer_cast<T>(p)` * {blank}
+
Returns:: `std::static_pointer_cast<T>(p)`
``` ```
template<class T, class U> std::unique_ptr<T> template<class T, class U> std::unique_ptr<T>
static_pointer_cast(std::unique_ptr<U>&& p) noexcept; static_pointer_cast(std::unique_ptr<U>&& p) noexcept;
``` ```
:: [none]
Requires::: The expression `static_cast<T*>((U*)0)` must be well-formed. * {blank}
Returns::: `std::unique_ptr<T>(static_cast<typename +
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()))`. std::unique_ptr<T>::element_type*>(p.release()))`.
CAUTION: The seemingly equivalent expression CAUTION: The seemingly equivalent expression
@@ -106,25 +112,31 @@ undefined behavior, attempting to delete the same object twice.
``` ```
template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept; template<class T, class U> T* dynamic_pointer_cast(U* p) noexcept;
``` ```
:: [none]
Returns::: `dynamic_cast<T*>(p)` * {blank}
+
Returns:: `dynamic_cast<T*>(p)`
``` ```
template<class T, class U> std::shared_ptr<T> template<class T, class U> std::shared_ptr<T>
dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept; dynamic_pointer_cast(const std::shared_ptr<U>& p) noexcept;
``` ```
:: [none]
Returns::: `std::dynamic_pointer_cast<T>(p)` * {blank}
+
Returns:: `std::dynamic_pointer_cast<T>(p)`
``` ```
template<class T, class U> std::unique_ptr<T> template<class T, class U> std::unique_ptr<T>
dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept; dynamic_pointer_cast(std::unique_ptr<U>&& p) noexcept;
``` ```
:: [none]
Requires::: * {blank}
+
Requires::
* The expression `static_cast<T*>((U*)0)` must be well-formed. * The expression `static_cast<T*>((U*)0)` must be well-formed.
* `T` must have a virtual destructor. * `T` must have a virtual destructor.
Returns::: Returns::
* When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())` * When `dynamic_cast<typename std::unique_ptr<T>::element_type*>(p.get())`
returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename returns a non-zero value, `std::unique_ptr<T>(dynamic_cast<typename
std::unique_ptr<T>::element_type*>(p.release()));`. std::unique_ptr<T>::element_type*>(p.release()));`.
@@ -135,23 +147,29 @@ std::unique_ptr<T>::element_type*>(p.release()));`.
``` ```
template<class T, class U> T* const_pointer_cast(U* p) noexcept; template<class T, class U> T* const_pointer_cast(U* p) noexcept;
``` ```
:: [none]
Returns::: `const_cast<T*>(p)` * {blank}
+
Returns:: `const_cast<T*>(p)`
``` ```
template<class T, class U> std::shared_ptr<T> template<class T, class U> std::shared_ptr<T>
const_pointer_cast(const std::shared_ptr<U>& p) noexcept; const_pointer_cast(const std::shared_ptr<U>& p) noexcept;
``` ```
:: [none]
Returns::: `std::const_pointer_cast<T>(p)` * {blank}
+
Returns:: `std::const_pointer_cast<T>(p)`
``` ```
template<class T, class U> std::unique_ptr<T> template<class T, class U> std::unique_ptr<T>
const_pointer_cast(std::unique_ptr<U>&& p) noexcept; const_pointer_cast(std::unique_ptr<U>&& p) noexcept;
``` ```
:: [none]
Requires::: The expression `const_cast<T*>((U*)0)` must be well-formed. * {blank}
Returns::: `std::unique_ptr<T>(const_cast<typename +
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()))`. std::unique_ptr<T>::element_type*>(p.release()))`.
### reinterpret_pointer_cast ### reinterpret_pointer_cast
@@ -159,23 +177,29 @@ std::unique_ptr<T>::element_type*>(p.release()))`.
``` ```
template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept; template<class T, class U> T* reinterpret_pointer_cast(U* p) noexcept;
``` ```
:: [none]
Returns::: `reinterpret_cast<T*>(p)` * {blank}
+
Returns:: `reinterpret_cast<T*>(p)`
``` ```
template<class T, class U> std::shared_ptr<T> template<class T, class U> std::shared_ptr<T>
reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept; reinterpret_pointer_cast(const std::shared_ptr<U>& p) noexcept;
``` ```
:: [none]
Returns::: `std::reinterpret_pointer_cast<T>(p)` * {blank}
+
Returns:: `std::reinterpret_pointer_cast<T>(p)`
``` ```
template<class T, class U> std::unique_ptr<T> template<class T, class U> std::unique_ptr<T>
reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept; reinterpret_pointer_cast(std::unique_ptr<U>&& p) noexcept;
``` ```
:: [none]
Requires::: The expression `reinterpret_cast<T*>((U*)0)` must be well-formed. * {blank}
Returns::: `std::unique_ptr<T>(reinterpret_cast<typename +
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()))`. std::unique_ptr<T>::element_type*>(p.release()))`.
## Example ## Example

View File

@@ -105,42 +105,50 @@ Type:: Provides the type of the stored pointer.
``` ```
explicit shared_array(T* p = 0); explicit shared_array(T* p = 0);
``` ```
:: [none]
Effects::: Constructs a `shared_array`, storing a copy of `p`, which must be a * {blank}
+
Effects:: Constructs a `shared_array`, storing a copy of `p`, which must be a
pointer to an array that was allocated via a C++ `new[]` expression or be 0. 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`). Afterwards, the use count is 1 (even if `p == 0`; see `~shared_array`).
Requires::: `T` is a complete type. Requires:: `T` is a complete type.
Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
``` ```
template<class D> shared_array(T* p, D d); template<class D> shared_array(T* p, D d);
``` ```
:: [none]
Effects::: Constructs a `shared_array`, storing a copy of `p` and of `d`. * {blank}
+
Effects:: Constructs a `shared_array`, storing a copy of `p` and of `d`.
Afterwards, the use count is 1. When the the time comes to delete the array 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)`. pointed to by `p`, the object `d` is used in the statement `d(p)`.
Requires::: Requires::
* `T` is a complete type. * `T` is a complete type.
* The copy constructor and destructor of `D` must not throw. * The copy constructor and destructor of `D` must not throw.
* Invoking the object `d` with parameter `p` 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. Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called.
``` ```
shared_array(const shared_array& v) noexcept; shared_array(const shared_array& v) noexcept;
``` ```
:: [none]
Effects::: Constructs a `shared_array`, as if by storing a copy of the pointer * {blank}
+
Effects:: Constructs a `shared_array`, as if by storing a copy of the pointer
stored in `v`. Afterwards, the use count for all copies is 1 more than the stored in `v`. Afterwards, the use count for all copies is 1 more than the
initial use count. initial use count.
Requires::: `T` is a complete type. Requires:: `T` is a complete type.
### Destructor ### Destructor
``` ```
~shared_array() noexcept; ~shared_array() noexcept;
``` ```
:: [none]
Effects::: Decrements the use count. Then, if the use count is 0, deletes the * {blank}
+
Effects:: Decrements the use count. Then, if the use count is 0, deletes the
array pointed to by the stored pointer. Note that `delete[]` on a pointer with array pointed to by the stored pointer. Note that `delete[]` on a pointer with
a value of 0 is harmless. a value of 0 is harmless.
@@ -149,60 +157,70 @@ a value of 0 is harmless.
``` ```
shared_array& operator=(const shared_array& v) noexcept; shared_array& operator=(const shared_array& v) noexcept;
``` ```
:: [none]
Effects::: Constructs a new `shared_array` as described above, then replaces * {blank}
+
Effects:: Constructs a new `shared_array` as described above, then replaces
this `shared_array` with the new one, destroying the replaced object. this `shared_array` with the new one, destroying the replaced object.
Requires::: `T` is a complete type. Requires:: `T` is a complete type.
Returns::: `*this`. Returns:: `*this`.
### reset ### reset
``` ```
void reset(T* p = 0); void reset(T* p = 0);
``` ```
:: [none]
Effects::: Constructs a new `shared_array` as described above, then replaces * {blank}
+
Effects:: Constructs a new `shared_array` as described above, then replaces
this `shared_array` with the new one, destroying the replaced object. this `shared_array` with the new one, destroying the replaced object.
Requires::: `T` is a complete type. Requires:: `T` is a complete type.
Throws::: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called. Throws:: `std::bad_alloc`. If an exception is thrown, `delete[] p` is called.
``` ```
template<class D> void reset(T* p, D d); template<class D> void reset(T* p, D d);
``` ```
:: [none]
Effects::: Constructs a new `shared_array` as described above, then replaces * {blank}
+
Effects:: Constructs a new `shared_array` as described above, then replaces
this `shared_array` with the new one, destroying the replaced object. this `shared_array` with the new one, destroying the replaced object.
Requires::: Requires::
* `T` is a complete type. * `T` is a complete type.
* The copy constructor of `D` must not throw. * The copy constructor of `D` must not throw.
Throws::: `std::bad_alloc`. If an exception is thrown, `d(p)` is called. Throws:: `std::bad_alloc`. If an exception is thrown, `d(p)` is called.
### Indexing ### Indexing
``` ```
T& operator[](std::ptrdiff_t n) const noexcept; T& operator[](std::ptrdiff_t n) const noexcept;
``` ```
Returns::: A reference to element `n` of the array pointed to by the stored 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. 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 pointer is 0, or if `n` is less than 0 or is greater than or equal to the
number of elements in the array. number of elements in the array.
Requires::: `T` is a complete type. Requires:: `T` is a complete type.
### get ### get
``` ```
T* get() const noexcept; T* get() const noexcept;
``` ```
:: [none]
Returns::: The stored pointer. * {blank}
+
Returns:: The stored pointer.
### unique ### unique
``` ```
bool unique() const noexcept; bool unique() const noexcept;
``` ```
:: [none]
Returns::: `true` if no other `shared_array` is sharing ownership of the * {blank}
+
Returns:: `true` if no other `shared_array` is sharing ownership of the
stored pointer, `false` otherwise. stored pointer, `false` otherwise.
### use_count ### use_count
@@ -210,8 +228,10 @@ stored pointer, `false` otherwise.
``` ```
long use_count() const noexcept; long use_count() const noexcept;
``` ```
:: [none]
Returns::: The number of `shared_array` objects sharing ownership of the * {blank}
+
Returns:: The number of `shared_array` objects sharing ownership of the
stored pointer. stored pointer.
### Conversions ### Conversions
@@ -219,17 +239,21 @@ stored pointer.
``` ```
explicit operator bool() const noexcept; explicit operator bool() const noexcept;
``` ```
:: [none]
Returns::: `get() != 0`. * {blank}
Requires::: `T` is a complete type. +
Returns:: `get() != 0`.
Requires:: `T` is a complete type.
### swap ### swap
``` ```
void swap(shared_array<T>& b) noexcept; void swap(shared_array<T>& b) noexcept;
``` ```
:: [none]
Effects::: Exchanges the contents of the two smart pointers. * {blank}
+
Effects:: Exchanges the contents of the two smart pointers.
## Free Functions ## Free Functions
@@ -247,8 +271,10 @@ template<class T> bool
template<class T> bool template<class T> bool
operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept; operator<(const shared_array<T>& a, const shared_array<T>& b) noexcept;
``` ```
:: [none]
Returns::: The result of comparing the stored pointers of the two smart * {blank}
+
Returns:: The result of comparing the stored pointers of the two smart
pointers. pointers.
NOTE: The `operator<` overload is provided to define an ordering so that NOTE: The `operator<` overload is provided to define an ordering so that
@@ -265,6 +291,8 @@ mandates that relational operations on pointers are unspecified (5.9
template<class T> template<class T>
void swap(shared_array<T>& a, shared_array<T>& b) noexcept; void swap(shared_array<T>& a, shared_array<T>& b) noexcept;
``` ```
:: [none]
Returns::: `a.swap(b)`. * {blank}
Requires::: `T` is a complete type. +
Returns:: `a.swap(b)`.
Requires:: `T` is a complete type.

View File

@@ -132,7 +132,6 @@ namespace boost {
template<class Y> shared_ptr(shared_ptr<Y> && r) noexcept; template<class Y> shared_ptr(shared_ptr<Y> && r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p) noexcept; template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p) noexcept; template<class Y> shared_ptr(shared_ptr<Y> && r, element_type * p) noexcept;
template<class Y> explicit shared_ptr(weak_ptr<Y> const & r); template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
@@ -373,7 +372,7 @@ template<class Y> shared_ptr(shared_ptr<Y> const & r, element_type * p) noexcept
[none] [none]
* {blank} * {blank}
+ +
Effects:: constructs a `shared_ptr` that shares ownership with `r` and stores `p`. Effects:: Copy-constructs a `shared_ptr` from `r`, while storing `p` instead.
Postconditions:: `get() == p && use_count() == r.use_count()`. Postconditions:: `get() == p && use_count() == r.use_count()`.

View File

@@ -88,6 +88,10 @@ namespace boost {
weak_ptr(weak_ptr && r) noexcept; weak_ptr(weak_ptr && r) noexcept;
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;
~weak_ptr() noexcept; ~weak_ptr() noexcept;
weak_ptr & operator=(weak_ptr const & r) noexcept; weak_ptr & operator=(weak_ptr const & r) noexcept;
@@ -98,6 +102,8 @@ namespace boost {
long use_count() const noexcept; long use_count() const noexcept;
bool expired() const noexcept; bool expired() const noexcept;
bool empty() const noexcept;
shared_ptr<T> lock() const noexcept; shared_ptr<T> lock() const noexcept;
void reset() noexcept; void reset() noexcept;
@@ -157,6 +163,21 @@ weak_ptr(weak_ptr && r) noexcept;
Effects:: Constructs a `weak_ptr` that has the value `r` held. Effects:: Constructs a `weak_ptr` that has the value `r` held.
Postconditions:: `r` is empty. Postconditions:: `r` is empty.
### aliasing constructors
```
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) noexcept;
```
```
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) noexcept;
```
```
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) noexcept;
```
Effects:: Constructs a `weak_ptr` from `r` as if by using the corresponding converting/copy/move constructor, but stores `p` instead.
Postconditions:: `use_count() == r.use_count()`. When `!expired()`, `shared_ptr<T>(*this).get() == p`.
NOTE: These constructors are an extension, not present in `std::weak_ptr`.
### destructor ### destructor
``` ```
~weak_ptr() noexcept; ~weak_ptr() noexcept;
@@ -204,6 +225,17 @@ bool expired() const noexcept;
+ +
Returns:: `use_count() == 0`. Returns:: `use_count() == 0`.
### empty
```
bool empty() const noexcept;
```
[none]
* {blank}
+
Returns:: `true` when `*this` is empty, `false` otherwise.
NOTE: This function is an extension, not present in `std::weak_ptr`.
### lock ### lock
``` ```
shared_ptr<T> lock() const noexcept; shared_ptr<T> lock() const noexcept;

View File

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

View File

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

View File

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

View File

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

View File

@@ -10,30 +10,59 @@
// boost/detail/lightweight_thread.hpp // boost/detail/lightweight_thread.hpp
// //
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. // Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2008 Peter Dimov // Copyright (c) 2008, 2018 Peter Dimov
// //
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at // See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt // http://www.boost.org/LICENSE_1_0.txt
//
//
// typedef /*...*/ lw_thread_t; // as pthread_t
// template<class F> int lw_thread_create( lw_thread_t & th, F f );
// void lw_thread_join( lw_thread_t th );
#include <boost/config.hpp> #include <boost/config.hpp>
#include <memory> #include <memory>
#include <cerrno> #include <cerrno>
// pthread_create, pthread_join
#if defined( BOOST_HAS_PTHREADS ) #if defined( BOOST_HAS_PTHREADS )
#include <pthread.h> #include <pthread.h>
#else namespace boost
{
namespace detail
{
typedef ::pthread_t lw_thread_t;
inline int lw_thread_create_( lw_thread_t* thread, const pthread_attr_t* attr, void* (*start_routine)( void* ), void* arg )
{
return ::pthread_create( thread, attr, start_routine, arg );
}
inline void lw_thread_join( lw_thread_t th )
{
::pthread_join( th, 0 );
}
} // namespace detail
} // namespace boost
#else // defined( BOOST_HAS_PTHREADS )
#include <windows.h> #include <windows.h>
#include <process.h> #include <process.h>
typedef HANDLE pthread_t; namespace boost
{
namespace detail
{
int pthread_create( pthread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg ) typedef HANDLE lw_thread_t;
inline int lw_thread_create_( lw_thread_t * thread, void const *, unsigned (__stdcall * start_routine) (void*), void* arg )
{ {
HANDLE h = (HANDLE)_beginthreadex( 0, 0, start_routine, arg, 0, 0 ); HANDLE h = (HANDLE)_beginthreadex( 0, 0, start_routine, arg, 0, 0 );
@@ -48,20 +77,20 @@ int pthread_create( pthread_t * thread, void const *, unsigned (__stdcall * star
} }
} }
int pthread_join( pthread_t thread, void ** /*value_ptr*/ ) inline void lw_thread_join( lw_thread_t thread )
{ {
::WaitForSingleObject( thread, INFINITE ); ::WaitForSingleObject( thread, INFINITE );
::CloseHandle( thread ); ::CloseHandle( thread );
return 0;
} }
#endif } // namespace detail
} // namespace boost
#endif // defined( BOOST_HAS_PTHREADS )
// template<class F> int lw_thread_create( pthread_t & pt, F f );
namespace boost namespace boost
{ {
namespace detail namespace detail
{ {
@@ -131,7 +160,7 @@ private:
F f_; F f_;
}; };
template<class F> int lw_thread_create( pthread_t & pt, F f ) template<class F> int lw_thread_create( lw_thread_t & th, F f )
{ {
#if defined(BOOST_NO_CXX11_SMART_PTR) #if defined(BOOST_NO_CXX11_SMART_PTR)
@@ -143,7 +172,7 @@ template<class F> int lw_thread_create( pthread_t & pt, F f )
#endif #endif
int r = pthread_create( &pt, 0, lw_thread_routine, p.get() ); int r = lw_thread_create_( &th, 0, lw_thread_routine, p.get() );
if( r == 0 ) if( r == 0 )
{ {

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2017 Glen Joseph Fernandes Copyright 2017-2019 Glen Joseph Fernandes
(glenjofe@gmail.com) (glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
@@ -14,23 +14,7 @@ Distributed under the Boost Software License, Version 1.0.
namespace boost { namespace boost {
namespace detail { namespace detail {
template<class> class BOOST_SYMBOL_VISIBLE lsp_array_base
struct lsp_if_array { };
template<class T>
struct lsp_if_array<T[]> {
typedef boost::local_shared_ptr<T[]> type;
};
template<class>
struct lsp_if_size_array { };
template<class T, std::size_t N>
struct lsp_if_size_array<T[N]> {
typedef boost::local_shared_ptr<T[N]> type;
};
class lsp_array_base
: public local_counted_base { : public local_counted_base {
public: public:
void set(sp_counted_base* base) BOOST_SP_NOEXCEPT { void set(sp_counted_base* base) BOOST_SP_NOEXCEPT {
@@ -84,15 +68,16 @@ private:
} /* detail */ } /* detail */
template<class T, class A> template<class T, class A>
inline typename detail::lsp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator, std::size_t count) allocate_local_shared(const A& allocator, std::size_t count)
{ {
typedef typename detail::sp_array_element<T>::type type; typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::lsp_array_state<other> state; typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
std::size_t size = count * detail::sp_array_count<type>::value; std::size_t size = count * detail::sp_array_count<type, scalar>::value;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get(); base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); scalar* start = detail::sp_array_start<base, scalar>(node);
@@ -105,15 +90,16 @@ allocate_local_shared(const A& allocator, std::size_t count)
} }
template<class T, class A> template<class T, class A>
inline typename detail::lsp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator) allocate_local_shared(const A& allocator)
{ {
enum { typedef typename remove_extent<T>::type type;
size = detail::sp_array_count<T>::value
};
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
typedef detail::lsp_size_array_state<other, size> state; typedef detail::lsp_size_array_state<other, size> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);
@@ -128,22 +114,25 @@ allocate_local_shared(const A& allocator)
} }
template<class T, class A> template<class T, class A>
inline typename detail::lsp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator, std::size_t count, allocate_local_shared(const A& allocator, std::size_t count,
const typename detail::sp_array_element<T>::type& value) const typename remove_extent<T>::type& value)
{ {
typedef typename detail::sp_array_element<T>::type type; typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::lsp_array_state<other> state; typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
std::size_t size = count * detail::sp_array_count<type>::value; enum {
total = detail::sp_array_count<type, scalar>::value
};
std::size_t size = count * total;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get(); base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); scalar* start = detail::sp_array_start<base, scalar>(node);
::new(static_cast<void*>(node)) base(allocator, size, ::new(static_cast<void*>(node)) base(allocator, size,
reinterpret_cast<const scalar*>(&value), reinterpret_cast<const scalar*>(&value), total, start);
detail::sp_array_count<type>::value, start);
detail::lsp_array_base& local = node->state().base(); detail::lsp_array_base& local = node->state().base();
local.set(node); local.set(node);
result.release(); result.release();
@@ -152,16 +141,17 @@ allocate_local_shared(const A& allocator, std::size_t count,
} }
template<class T, class A> template<class T, class A>
inline typename detail::lsp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator, allocate_local_shared(const A& allocator,
const typename detail::sp_array_element<T>::type& value) const typename remove_extent<T>::type& value)
{ {
enum { typedef typename remove_extent<T>::type type;
size = detail::sp_array_count<T>::value
};
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
typedef detail::lsp_size_array_state<other, size> state; typedef detail::lsp_size_array_state<other, size> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);
@@ -169,7 +159,7 @@ allocate_local_shared(const A& allocator,
scalar* start = detail::sp_array_start<base, scalar>(node); scalar* start = detail::sp_array_start<base, scalar>(node);
::new(static_cast<void*>(node)) base(allocator, size, ::new(static_cast<void*>(node)) base(allocator, size,
reinterpret_cast<const scalar*>(&value), reinterpret_cast<const scalar*>(&value),
detail::sp_array_count<type>::value, start); detail::sp_array_count<type, scalar>::value, start);
detail::lsp_array_base& local = node->state().base(); detail::lsp_array_base& local = node->state().base();
local.set(node); local.set(node);
result.release(); result.release();
@@ -178,15 +168,16 @@ allocate_local_shared(const A& allocator,
} }
template<class T, class A> template<class T, class A>
inline typename detail::lsp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared_noinit(const A& allocator, std::size_t count) allocate_local_shared_noinit(const A& allocator, std::size_t count)
{ {
typedef typename detail::sp_array_element<T>::type type; typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::lsp_array_state<other> state; typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state, false> base; typedef detail::sp_array_base<state, false> base;
std::size_t size = count * detail::sp_array_count<type>::value; std::size_t size = count * detail::sp_array_count<type, scalar>::value;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get(); base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); scalar* start = detail::sp_array_start<base, scalar>(node);
@@ -200,15 +191,16 @@ allocate_local_shared_noinit(const A& allocator, std::size_t count)
} }
template<class T, class A> template<class T, class A>
inline typename detail::lsp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
allocate_local_shared_noinit(const A& allocator) allocate_local_shared_noinit(const A& allocator)
{ {
enum { typedef typename remove_extent<T>::type type;
size = detail::sp_array_count<T>::value
};
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
typedef detail::lsp_size_array_state<other, size> state; typedef detail::lsp_size_array_state<other, size> state;
typedef detail::sp_array_base<state, false> base; typedef detail::sp_array_base<state, false> base;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012-2017 Glen Joseph Fernandes Copyright 2012-2019 Glen Joseph Fernandes
(glenjofe@gmail.com) (glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
@@ -10,99 +10,30 @@ Distributed under the Boost Software License, Version 1.0.
#include <boost/smart_ptr/shared_ptr.hpp> #include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/type_traits/alignment_of.hpp> #include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/is_bounded_array.hpp>
#include <boost/type_traits/is_unbounded_array.hpp>
#include <boost/type_traits/has_trivial_assign.hpp> #include <boost/type_traits/has_trivial_assign.hpp>
#include <boost/type_traits/has_trivial_constructor.hpp> #include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp> #include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/type_traits/remove_all_extents.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/type_with_alignment.hpp> #include <boost/type_traits/type_with_alignment.hpp>
namespace boost { namespace boost {
namespace detail { namespace detail {
template<class>
struct sp_if_array { };
template<class T>
struct sp_if_array<T[]> {
typedef boost::shared_ptr<T[]> type;
};
template<class>
struct sp_if_size_array { };
template<class T, std::size_t N>
struct sp_if_size_array<T[N]> {
typedef boost::shared_ptr<T[N]> type;
};
template<class>
struct sp_array_element { };
template<class T>
struct sp_array_element<T[]> {
typedef T type;
};
template<class T, std::size_t N>
struct sp_array_element<T[N]> {
typedef T type;
};
template<class T> template<class T>
struct sp_array_scalar { struct sp_array_scalar {
typedef T type; typedef typename boost::remove_cv<typename
boost::remove_all_extents<T>::type>::type type;
}; };
template<class T, std::size_t N> template<class T, class U>
struct sp_array_scalar<T[N]> {
typedef typename sp_array_scalar<T>::type type;
};
template<class T, std::size_t N>
struct sp_array_scalar<const T[N]> {
typedef typename sp_array_scalar<T>::type type;
};
template<class T, std::size_t N>
struct sp_array_scalar<volatile T[N]> {
typedef typename sp_array_scalar<T>::type type;
};
template<class T, std::size_t N>
struct sp_array_scalar<const volatile T[N]> {
typedef typename sp_array_scalar<T>::type type;
};
template<class T>
struct sp_array_scalar<T[]> {
typedef typename sp_array_scalar<T>::type type;
};
template<class T>
struct sp_array_scalar<const T[]> {
typedef typename sp_array_scalar<T>::type type;
};
template<class T>
struct sp_array_scalar<volatile T[]> {
typedef typename sp_array_scalar<T>::type type;
};
template<class T>
struct sp_array_scalar<const volatile T[]> {
typedef typename sp_array_scalar<T>::type type;
};
template<class T>
struct sp_array_count { struct sp_array_count {
enum { enum {
value = 1 value = sizeof(T) / sizeof(U)
};
};
template<class T, std::size_t N>
struct sp_array_count<T[N]> {
enum {
value = N * sp_array_count<T>::value
}; };
}; };
@@ -139,213 +70,153 @@ sp_objects(std::size_t size) BOOST_SP_NOEXCEPT
return (size + sizeof(T) - 1) / sizeof(T); return (size + sizeof(T) - 1) / sizeof(T);
} }
template<bool, class = void>
struct sp_enable { };
template<class T>
struct sp_enable<true, T> {
typedef T type;
};
template<bool E, class A, class T> template<bool E, class A, class T>
inline typename sp_enable<!E && boost::has_trivial_destructor<T>::value>::type inline typename boost::enable_if_<!E &&
boost::has_trivial_destructor<T>::value>::type
sp_array_destroy(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { } sp_array_destroy(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
template<bool E, class A, class T> template<bool E, class A, class T>
inline typename sp_enable<!E && inline typename boost::enable_if_<!E &&
!boost::has_trivial_destructor<T>::value>::type !boost::has_trivial_destructor<T>::value>::type
sp_array_destroy(A&, T* start, std::size_t size) sp_array_destroy(A&, T* ptr, std::size_t size)
{ {
while (size > 0) { while (size > 0) {
start[--size].~T(); ptr[--size].~T();
} }
} }
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<bool E, class A, class T> template<bool E, class A, class T>
inline typename sp_enable<E>::type inline typename boost::enable_if_<E>::type
sp_array_destroy(A& allocator, T* start, std::size_t size) sp_array_destroy(A& allocator, T* ptr, std::size_t size)
{ {
while (size > 0) { while (size > 0) {
std::allocator_traits<A>::destroy(allocator, start + --size); std::allocator_traits<A>::destroy(allocator, ptr + --size);
} }
} }
#endif #endif
template<bool E, class A, class T> template<bool E, class A, class T>
inline typename sp_enable<!E && class sp_destroyer {
public:
sp_destroyer(A& allocator, T* ptr) BOOST_SP_NOEXCEPT
: allocator_(allocator),
ptr_(ptr),
size_(0) { }
~sp_destroyer() {
sp_array_destroy<E>(allocator_, ptr_, size_);
}
std::size_t& size() BOOST_SP_NOEXCEPT {
return size_;
}
private:
sp_destroyer(const sp_destroyer&);
sp_destroyer& operator=(const sp_destroyer&);
A& allocator_;
T* ptr_;
std::size_t size_;
};
template<bool E, class A, class T>
inline typename boost::enable_if_<!E &&
boost::has_trivial_constructor<T>::value && boost::has_trivial_constructor<T>::value &&
boost::has_trivial_assign<T>::value && boost::has_trivial_assign<T>::value &&
boost::has_trivial_destructor<T>::value>::type boost::has_trivial_destructor<T>::value>::type
sp_array_construct(A&, T* start, std::size_t size) sp_array_construct(A&, T* ptr, std::size_t size)
{ {
for (std::size_t i = 0; i < size; ++i) { for (std::size_t i = 0; i < size; ++i) {
start[i] = T(); ptr[i] = T();
} }
} }
template<bool E, class A, class T> template<bool E, class A, class T>
inline typename sp_enable<!E && inline typename boost::enable_if_<!E &&
boost::has_trivial_constructor<T>::value && boost::has_trivial_constructor<T>::value &&
boost::has_trivial_assign<T>::value && boost::has_trivial_assign<T>::value &&
boost::has_trivial_destructor<T>::value>::type boost::has_trivial_destructor<T>::value>::type
sp_array_construct(A&, T* start, std::size_t size, const T* list, sp_array_construct(A&, T* ptr, std::size_t size, const T* list,
std::size_t count) std::size_t count)
{ {
for (std::size_t i = 0; i < size; ++i) { for (std::size_t i = 0; i < size; ++i) {
start[i] = list[i % count]; ptr[i] = list[i % count];
}
}
#if !defined(BOOST_NO_EXCEPTIONS)
template<bool E, class A, class T>
inline typename sp_enable<!E &&
!(boost::has_trivial_constructor<T>::value &&
boost::has_trivial_assign<T>::value &&
boost::has_trivial_destructor<T>::value)>::type
sp_array_construct(A& none, T* start, std::size_t size)
{
std::size_t i = 0;
try {
for (; i < size; ++i) {
::new(static_cast<void*>(start + i)) T();
}
} catch (...) {
sp_array_destroy<E>(none, start, i);
throw;
} }
} }
template<bool E, class A, class T> template<bool E, class A, class T>
inline typename sp_enable<!E && inline typename boost::enable_if_<!E &&
!(boost::has_trivial_constructor<T>::value && !(boost::has_trivial_constructor<T>::value &&
boost::has_trivial_assign<T>::value && boost::has_trivial_assign<T>::value &&
boost::has_trivial_destructor<T>::value)>::type boost::has_trivial_destructor<T>::value)>::type
sp_array_construct(A& none, T* start, std::size_t size, const T* list, sp_array_construct(A& none, T* ptr, std::size_t size)
std::size_t count)
{ {
std::size_t i = 0; sp_destroyer<E, A, T> hold(none, ptr);
try { for (std::size_t& i = hold.size(); i < size; ++i) {
for (; i < size; ++i) { ::new(static_cast<void*>(ptr + i)) T();
::new(static_cast<void*>(start + i)) T(list[i % count]);
}
} catch (...) {
sp_array_destroy<E>(none, start, i);
throw;
}
}
#else
template<bool E, class A, class T>
inline typename sp_enable<!E &&
!(boost::has_trivial_constructor<T>::value &&
boost::has_trivial_assign<T>::value &&
boost::has_trivial_destructor<T>::value)>::type
sp_array_construct(A&, T* start, std::size_t size)
{
for (std::size_t i = 0; i < size; ++i) {
::new(static_cast<void*>(start + i)) T();
} }
hold.size() = 0;
} }
template<bool E, class A, class T> template<bool E, class A, class T>
inline typename sp_enable<!E && inline typename boost::enable_if_<!E &&
!(boost::has_trivial_constructor<T>::value && !(boost::has_trivial_constructor<T>::value &&
boost::has_trivial_assign<T>::value && boost::has_trivial_assign<T>::value &&
boost::has_trivial_destructor<T>::value)>::type boost::has_trivial_destructor<T>::value)>::type
sp_array_construct(A&, T* start, std::size_t size, const T* list, sp_array_construct(A& none, T* ptr, std::size_t size, const T* list,
std::size_t count) std::size_t count)
{ {
for (std::size_t i = 0; i < size; ++i) { sp_destroyer<E, A, T> hold(none, ptr);
::new(static_cast<void*>(start + i)) T(list[i % count]); for (std::size_t& i = hold.size(); i < size; ++i) {
::new(static_cast<void*>(ptr + i)) T(list[i % count]);
} }
hold.size() = 0;
} }
#endif
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
#if !defined(BOOST_NO_EXCEPTIONS)
template<bool E, class A, class T> template<bool E, class A, class T>
inline typename sp_enable<E>::type inline typename boost::enable_if_<E>::type
sp_array_construct(A& allocator, T* start, std::size_t size) sp_array_construct(A& allocator, T* ptr, std::size_t size)
{ {
std::size_t i = 0; sp_destroyer<E, A, T> hold(allocator, ptr);
try { for (std::size_t& i = hold.size(); i < size; ++i) {
for (i = 0; i < size; ++i) { std::allocator_traits<A>::construct(allocator, ptr + i);
std::allocator_traits<A>::construct(allocator, start + i);
}
} catch (...) {
sp_array_destroy<E>(allocator, start, i);
throw;
} }
hold.size() = 0;
} }
template<bool E, class A, class T> template<bool E, class A, class T>
inline typename sp_enable<E>::type inline typename boost::enable_if_<E>::type
sp_array_construct(A& allocator, T* start, std::size_t size, const T* list, sp_array_construct(A& allocator, T* ptr, std::size_t size, const T* list,
std::size_t count) std::size_t count)
{ {
std::size_t i = 0; sp_destroyer<E, A, T> hold(allocator, ptr);
try { for (std::size_t& i = hold.size(); i < size; ++i) {
for (i = 0; i < size; ++i) { std::allocator_traits<A>::construct(allocator, ptr + i,
std::allocator_traits<A>::construct(allocator, start + i,
list[i % count]); list[i % count]);
} }
} catch (...) { hold.size() = 0;
sp_array_destroy<E>(allocator, start, i);
throw;
}
} }
#else
template<bool E, class A, class T>
inline typename sp_enable<E>::type
sp_array_construct(A& allocator, T* start, std::size_t size)
{
for (std::size_t i = 0; i < size; ++i) {
std::allocator_traits<A>::construct(allocator, start + i);
}
}
template<bool E, class A, class T>
inline typename sp_enable<E>::type
sp_array_construct(A& allocator, T* start, std::size_t size, const T* list,
std::size_t count)
{
for (std::size_t i = 0; i < size; ++i) {
std::allocator_traits<A>::construct(allocator, start + i,
list[i % count]);
}
}
#endif
#endif #endif
template<class A, class T> template<class A, class T>
inline typename sp_enable<boost::has_trivial_constructor<T>::value>::type inline typename
boost::enable_if_<boost::has_trivial_constructor<T>::value>::type
sp_array_default(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { } sp_array_default(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { }
#if !defined(BOOST_NO_EXCEPTIONS)
template<class A, class T> template<class A, class T>
inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type inline typename
sp_array_default(A& none, T* start, std::size_t size) boost::enable_if_<!boost::has_trivial_constructor<T>::value>::type
sp_array_default(A& none, T* ptr, std::size_t size)
{ {
std::size_t i = 0; sp_destroyer<false, A, T> hold(none, ptr);
try { for (std::size_t& i = hold.size(); i < size; ++i) {
for (; i < size; ++i) { ::new(static_cast<void*>(ptr + i)) T;
::new(static_cast<void*>(start + i)) T;
}
} catch (...) {
sp_array_destroy<false>(none, start, i);
throw;
} }
hold.size() = 0;
} }
#else
template<bool E, class A, class T>
inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type
sp_array_default(A&, T* start, std::size_t size)
{
for (std::size_t i = 0; i < size; ++i) {
::new(static_cast<void*>(start + i)) T;
}
}
#endif
template<class A> template<class A>
class sp_array_state { class sp_array_state {
@@ -479,7 +350,7 @@ private:
struct sp_default { }; struct sp_default { };
template<class T, bool E = sp_use_construct<T>::value> template<class T, bool E = sp_use_construct<T>::value>
class sp_array_base class BOOST_SYMBOL_VISIBLE sp_array_base
: public sp_counted_base { : public sp_counted_base {
typedef typename T::type allocator; typedef typename T::type allocator;
@@ -510,27 +381,27 @@ public:
return state_; return state_;
} }
virtual void dispose() { virtual void dispose() BOOST_SP_NOEXCEPT {
sp_array_destroy<E>(state_.allocator(), sp_array_destroy<E>(state_.allocator(),
sp_array_start<sp_array_base, type>(this), state_.size()); sp_array_start<sp_array_base, type>(this), state_.size());
} }
virtual void destroy() { virtual void destroy() BOOST_SP_NOEXCEPT {
sp_array_creator<allocator, sp_array_base> other(state_.allocator(), sp_array_creator<allocator, sp_array_base> other(state_.allocator(),
state_.size()); state_.size());
this->~sp_array_base(); this->~sp_array_base();
other.destroy(this); other.destroy(this);
} }
virtual void* get_deleter(const sp_typeinfo&) { virtual void* get_deleter(const sp_typeinfo&) BOOST_SP_NOEXCEPT {
return 0; return 0;
} }
virtual void* get_local_deleter(const sp_typeinfo&) { virtual void* get_local_deleter(const sp_typeinfo&) BOOST_SP_NOEXCEPT {
return 0; return 0;
} }
virtual void* get_untyped_deleter() { virtual void* get_untyped_deleter() BOOST_SP_NOEXCEPT {
return 0; return 0;
} }
@@ -571,15 +442,15 @@ private:
} /* detail */ } /* detail */
template<class T, class A> template<class T, class A>
inline typename detail::sp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, std::size_t count) allocate_shared(const A& allocator, std::size_t count)
{ {
typedef typename detail::sp_array_element<T>::type type; typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::sp_array_state<other> state; typedef detail::sp_array_state<other> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
std::size_t size = count * detail::sp_array_count<type>::value; std::size_t size = count * detail::sp_array_count<type, scalar>::value;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);
detail::sp_counted_base* node = result.get(); detail::sp_counted_base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); scalar* start = detail::sp_array_start<base, scalar>(node);
@@ -590,15 +461,15 @@ allocate_shared(const A& allocator, std::size_t count)
} }
template<class T, class A> template<class T, class A>
inline typename detail::sp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator) allocate_shared(const A& allocator)
{ {
enum { typedef typename remove_extent<T>::type type;
size = detail::sp_array_count<T>::value
};
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
typedef detail::sp_size_array_state<other, size> state; typedef detail::sp_size_array_state<other, size> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);
@@ -611,38 +482,40 @@ allocate_shared(const A& allocator)
} }
template<class T, class A> template<class T, class A>
inline typename detail::sp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, std::size_t count, allocate_shared(const A& allocator, std::size_t count,
const typename detail::sp_array_element<T>::type& value) const typename remove_extent<T>::type& value)
{ {
typedef typename detail::sp_array_element<T>::type type; typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::sp_array_state<other> state; typedef detail::sp_array_state<other> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
std::size_t size = count * detail::sp_array_count<type>::value; enum {
total = detail::sp_array_count<type, scalar>::value
};
std::size_t size = count * total;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);
detail::sp_counted_base* node = result.get(); detail::sp_counted_base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); scalar* start = detail::sp_array_start<base, scalar>(node);
::new(static_cast<void*>(node)) base(allocator, size, ::new(static_cast<void*>(node)) base(allocator, size,
reinterpret_cast<const scalar*>(&value), reinterpret_cast<const scalar*>(&value), total, start);
detail::sp_array_count<type>::value, start);
result.release(); result.release();
return shared_ptr<T>(detail::sp_internal_constructor_tag(), return shared_ptr<T>(detail::sp_internal_constructor_tag(),
reinterpret_cast<type*>(start), detail::shared_count(node)); reinterpret_cast<type*>(start), detail::shared_count(node));
} }
template<class T, class A> template<class T, class A>
inline typename detail::sp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, allocate_shared(const A& allocator,
const typename detail::sp_array_element<T>::type& value) const typename remove_extent<T>::type& value)
{ {
enum { typedef typename remove_extent<T>::type type;
size = detail::sp_array_count<T>::value
};
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
typedef detail::sp_size_array_state<other, size> state; typedef detail::sp_size_array_state<other, size> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);
@@ -650,22 +523,22 @@ allocate_shared(const A& allocator,
scalar* start = detail::sp_array_start<base, scalar>(node); scalar* start = detail::sp_array_start<base, scalar>(node);
::new(static_cast<void*>(node)) base(allocator, size, ::new(static_cast<void*>(node)) base(allocator, size,
reinterpret_cast<const scalar*>(&value), reinterpret_cast<const scalar*>(&value),
detail::sp_array_count<type>::value, start); detail::sp_array_count<type, scalar>::value, start);
result.release(); result.release();
return shared_ptr<T>(detail::sp_internal_constructor_tag(), return shared_ptr<T>(detail::sp_internal_constructor_tag(),
reinterpret_cast<type*>(start), detail::shared_count(node)); reinterpret_cast<type*>(start), detail::shared_count(node));
} }
template<class T, class A> template<class T, class A>
inline typename detail::sp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared_noinit(const A& allocator, std::size_t count) allocate_shared_noinit(const A& allocator, std::size_t count)
{ {
typedef typename detail::sp_array_element<T>::type type; typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::sp_array_state<other> state; typedef detail::sp_array_state<other> state;
typedef detail::sp_array_base<state, false> base; typedef detail::sp_array_base<state, false> base;
std::size_t size = count * detail::sp_array_count<type>::value; std::size_t size = count * detail::sp_array_count<type, scalar>::value;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);
detail::sp_counted_base* node = result.get(); detail::sp_counted_base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); scalar* start = detail::sp_array_start<base, scalar>(node);
@@ -677,15 +550,15 @@ allocate_shared_noinit(const A& allocator, std::size_t count)
} }
template<class T, class A> template<class T, class A>
inline typename detail::sp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared_noinit(const A& allocator) allocate_shared_noinit(const A& allocator)
{ {
enum { typedef typename remove_extent<T>::type type;
size = detail::sp_array_count<T>::value
};
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other; typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T, scalar>::value
};
typedef detail::sp_size_array_state<other, size> state; typedef detail::sp_size_array_state<other, size> state;
typedef detail::sp_array_base<state, false> base; typedef detail::sp_array_base<state, false> base;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, size);

View File

@@ -63,6 +63,11 @@ public:
{ {
} }
atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
: p_( std::move( p ) ), l_ BOOST_DETAIL_SPINLOCK_INIT
{
}
#else #else
atomic_shared_ptr() BOOST_SP_NOEXCEPT atomic_shared_ptr() BOOST_SP_NOEXCEPT
@@ -71,8 +76,6 @@ public:
std::memcpy( &l_, &init, sizeof( init ) ); std::memcpy( &l_, &init, sizeof( init ) );
} }
#endif
atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
: p_( std::move( p ) ) : p_( std::move( p ) )
@@ -84,6 +87,8 @@ public:
std::memcpy( &l_, &init, sizeof( init ) ); std::memcpy( &l_, &init, sizeof( init ) );
} }
#endif
atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT
{ {
boost::detail::spinlock::scoped_lock lock( l_ ); boost::detail::spinlock::scoped_lock lock( l_ );

View File

@@ -47,7 +47,7 @@ class bad_weak_ptr: public std::exception
{ {
public: public:
virtual char const * what() const throw() virtual char const * what() const BOOST_NOEXCEPT_OR_NOTHROW
{ {
return "tr1::bad_weak_ptr"; return "tr1::bad_weak_ptr";
} }

View File

@@ -27,7 +27,7 @@ namespace boost
namespace detail namespace detail
{ {
class local_counted_base class BOOST_SYMBOL_VISIBLE local_counted_base
{ {
private: private:
@@ -89,7 +89,7 @@ public:
} }
}; };
class local_counted_impl: public local_counted_base class BOOST_SYMBOL_VISIBLE local_counted_impl: public local_counted_base
{ {
private: private:
@@ -101,13 +101,13 @@ private:
public: public:
explicit local_counted_impl( shared_count const& pn ): pn_( pn ) explicit local_counted_impl( shared_count const& pn ) BOOST_SP_NOEXCEPT: pn_( pn )
{ {
} }
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
explicit local_counted_impl( shared_count && pn ): pn_( std::move(pn) ) explicit local_counted_impl( shared_count && pn ) BOOST_SP_NOEXCEPT: pn_( std::move(pn) )
{ {
} }
@@ -124,7 +124,7 @@ public:
} }
}; };
class local_counted_impl_em: public local_counted_base class BOOST_SYMBOL_VISIBLE local_counted_impl_em: public local_counted_base
{ {
public: public:

View File

@@ -50,7 +50,7 @@ public:
#endif #endif
D& deleter() D& deleter() BOOST_SP_NOEXCEPT
{ {
return d_; return d_;
} }
@@ -74,12 +74,12 @@ template<> class local_sp_deleter<void>
{ {
}; };
template<class D> D * get_local_deleter( local_sp_deleter<D> * p ) template<class D> D * get_local_deleter( local_sp_deleter<D> * p ) BOOST_SP_NOEXCEPT
{ {
return &p->deleter(); return &p->deleter();
} }
inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ ) inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ ) BOOST_SP_NOEXCEPT
{ {
return 0; return 0;
} }

View File

@@ -61,7 +61,9 @@ extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(::_RTL_CRIT
extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *); extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *);
extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *); extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *);
#else typedef ::_RTL_CRITICAL_SECTION rtl_critical_section;
#else // #ifndef BOOST_USE_WINDOWS_H
typedef ::CRITICAL_SECTION critical_section; typedef ::CRITICAL_SECTION critical_section;
@@ -74,6 +76,8 @@ using ::EnterCriticalSection;
using ::LeaveCriticalSection; using ::LeaveCriticalSection;
using ::DeleteCriticalSection; using ::DeleteCriticalSection;
typedef ::CRITICAL_SECTION rtl_critical_section;
#endif // #ifndef BOOST_USE_WINDOWS_H #endif // #ifndef BOOST_USE_WINDOWS_H
class lightweight_mutex class lightweight_mutex
@@ -90,15 +94,15 @@ public:
lightweight_mutex() lightweight_mutex()
{ {
#if BOOST_PLAT_WINDOWS_RUNTIME #if BOOST_PLAT_WINDOWS_RUNTIME
boost::detail::InitializeCriticalSectionEx(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&cs_), 4000, 0); boost::detail::InitializeCriticalSectionEx(reinterpret_cast< rtl_critical_section* >(&cs_), 4000, 0);
#else #else
boost::detail::InitializeCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&cs_)); boost::detail::InitializeCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_));
#endif #endif
} }
~lightweight_mutex() ~lightweight_mutex()
{ {
boost::detail::DeleteCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&cs_)); boost::detail::DeleteCriticalSection(reinterpret_cast< rtl_critical_section* >(&cs_));
} }
class scoped_lock; class scoped_lock;
@@ -117,12 +121,12 @@ public:
explicit scoped_lock(lightweight_mutex & m): m_(m) explicit scoped_lock(lightweight_mutex & m): m_(m)
{ {
boost::detail::EnterCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_.cs_)); boost::detail::EnterCriticalSection(reinterpret_cast< rtl_critical_section* >(&m_.cs_));
} }
~scoped_lock() ~scoped_lock()
{ {
boost::detail::LeaveCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_.cs_)); boost::detail::LeaveCriticalSection(reinterpret_cast< rtl_critical_section* >(&m_.cs_));
} }
}; };
}; };

View File

@@ -29,7 +29,8 @@
#include <boost/smart_ptr/detail/sp_counted_base.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_counted_impl.hpp>
#include <boost/smart_ptr/detail/sp_disable_deprecated.hpp> #include <boost/smart_ptr/detail/sp_disable_deprecated.hpp>
#include <boost/detail/workaround.hpp> #include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config/workaround.hpp>
// In order to avoid circular dependencies with Boost.TR1 // In order to avoid circular dependencies with Boost.TR1
// we make sure that our include of <memory> doesn't try to // we make sure that our include of <memory> doesn't try to
// pull in the TR1 headers: that's why we use this header // pull in the TR1 headers: that's why we use this header
@@ -118,14 +119,14 @@ private:
public: public:
BOOST_CONSTEXPR shared_count(): pi_(0) // nothrow BOOST_CONSTEXPR shared_count() BOOST_SP_NOEXCEPT: pi_(0)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id) , id_(shared_count_id)
#endif #endif
{ {
} }
BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ): pi_( pi ) // nothrow BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ) BOOST_SP_NOEXCEPT: pi_( pi )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id) , id_(shared_count_id)
#endif #endif
@@ -421,7 +422,7 @@ public:
r.release(); r.release();
} }
~shared_count() // nothrow ~shared_count() /*BOOST_SP_NOEXCEPT*/
{ {
if( pi_ != 0 ) pi_->release(); if( pi_ != 0 ) pi_->release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
@@ -429,7 +430,7 @@ public:
#endif #endif
} }
shared_count(shared_count const & r): pi_(r.pi_) // nothrow shared_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id) , id_(shared_count_id)
#endif #endif
@@ -439,7 +440,7 @@ public:
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
shared_count(shared_count && r): pi_(r.pi_) // nothrow shared_count(shared_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id) , id_(shared_count_id)
#endif #endif
@@ -450,9 +451,9 @@ public:
#endif #endif
explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0 explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
shared_count( weak_count const & r, sp_nothrow_tag ); // constructs an empty *this when r.use_count() == 0 shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT; // constructs an empty *this when r.use_count() == 0
shared_count & operator= (shared_count const & r) // nothrow shared_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
{ {
sp_counted_base * tmp = r.pi_; sp_counted_base * tmp = r.pi_;
@@ -466,49 +467,49 @@ public:
return *this; return *this;
} }
void swap(shared_count & r) // nothrow void swap(shared_count & r) BOOST_SP_NOEXCEPT
{ {
sp_counted_base * tmp = r.pi_; sp_counted_base * tmp = r.pi_;
r.pi_ = pi_; r.pi_ = pi_;
pi_ = tmp; pi_ = tmp;
} }
long use_count() const // nothrow long use_count() const BOOST_SP_NOEXCEPT
{ {
return pi_ != 0? pi_->use_count(): 0; return pi_ != 0? pi_->use_count(): 0;
} }
bool unique() const // nothrow bool unique() const BOOST_SP_NOEXCEPT
{ {
return use_count() == 1; return use_count() == 1;
} }
bool empty() const // nothrow bool empty() const BOOST_SP_NOEXCEPT
{ {
return pi_ == 0; return pi_ == 0;
} }
friend inline bool operator==(shared_count const & a, shared_count const & b) friend inline bool operator==(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
{ {
return a.pi_ == b.pi_; return a.pi_ == b.pi_;
} }
friend inline bool operator<(shared_count const & a, shared_count const & b) friend inline bool operator<(shared_count const & a, shared_count const & b) BOOST_SP_NOEXCEPT
{ {
return std::less<sp_counted_base *>()( a.pi_, b.pi_ ); return std::less<sp_counted_base *>()( a.pi_, b.pi_ );
} }
void * get_deleter( sp_typeinfo const & ti ) const void * get_deleter( sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
{ {
return pi_? pi_->get_deleter( ti ): 0; return pi_? pi_->get_deleter( ti ): 0;
} }
void * get_local_deleter( sp_typeinfo const & ti ) const void * get_local_deleter( sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT
{ {
return pi_? pi_->get_local_deleter( ti ): 0; return pi_? pi_->get_local_deleter( ti ): 0;
} }
void * get_untyped_deleter() const void * get_untyped_deleter() const BOOST_SP_NOEXCEPT
{ {
return pi_? pi_->get_untyped_deleter(): 0; return pi_? pi_->get_untyped_deleter(): 0;
} }
@@ -529,14 +530,14 @@ private:
public: public:
BOOST_CONSTEXPR weak_count(): pi_(0) // nothrow BOOST_CONSTEXPR weak_count() BOOST_SP_NOEXCEPT: pi_(0)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id) , id_(weak_count_id)
#endif #endif
{ {
} }
weak_count(shared_count const & r): pi_(r.pi_) // nothrow weak_count(shared_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id) , id_(weak_count_id)
#endif #endif
@@ -544,7 +545,7 @@ public:
if(pi_ != 0) pi_->weak_add_ref(); if(pi_ != 0) pi_->weak_add_ref();
} }
weak_count(weak_count const & r): pi_(r.pi_) // nothrow weak_count(weak_count const & r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id) , id_(weak_count_id)
#endif #endif
@@ -556,7 +557,7 @@ public:
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
weak_count(weak_count && r): pi_(r.pi_) // nothrow weak_count(weak_count && r) BOOST_SP_NOEXCEPT: pi_(r.pi_)
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(weak_count_id) , id_(weak_count_id)
#endif #endif
@@ -566,7 +567,7 @@ public:
#endif #endif
~weak_count() // nothrow ~weak_count() /*BOOST_SP_NOEXCEPT*/
{ {
if(pi_ != 0) pi_->weak_release(); if(pi_ != 0) pi_->weak_release();
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
@@ -574,7 +575,7 @@ public:
#endif #endif
} }
weak_count & operator= (shared_count const & r) // nothrow weak_count & operator= (shared_count const & r) BOOST_SP_NOEXCEPT
{ {
sp_counted_base * tmp = r.pi_; sp_counted_base * tmp = r.pi_;
@@ -588,7 +589,7 @@ public:
return *this; return *this;
} }
weak_count & operator= (weak_count const & r) // nothrow weak_count & operator= (weak_count const & r) BOOST_SP_NOEXCEPT
{ {
sp_counted_base * tmp = r.pi_; sp_counted_base * tmp = r.pi_;
@@ -602,29 +603,29 @@ public:
return *this; return *this;
} }
void swap(weak_count & r) // nothrow void swap(weak_count & r) BOOST_SP_NOEXCEPT
{ {
sp_counted_base * tmp = r.pi_; sp_counted_base * tmp = r.pi_;
r.pi_ = pi_; r.pi_ = pi_;
pi_ = tmp; pi_ = tmp;
} }
long use_count() const // nothrow long use_count() const BOOST_SP_NOEXCEPT
{ {
return pi_ != 0? pi_->use_count(): 0; return pi_ != 0? pi_->use_count(): 0;
} }
bool empty() const // nothrow bool empty() const BOOST_SP_NOEXCEPT
{ {
return pi_ == 0; return pi_ == 0;
} }
friend inline bool operator==(weak_count const & a, weak_count const & b) friend inline bool operator==(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
{ {
return a.pi_ == b.pi_; return a.pi_ == b.pi_;
} }
friend inline bool operator<(weak_count const & a, weak_count const & b) friend inline bool operator<(weak_count const & a, weak_count const & b) BOOST_SP_NOEXCEPT
{ {
return std::less<sp_counted_base *>()(a.pi_, b.pi_); return std::less<sp_counted_base *>()(a.pi_, b.pi_);
} }
@@ -641,7 +642,7 @@ inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ )
} }
} }
inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ): pi_( r.pi_ ) inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ) BOOST_SP_NOEXCEPT: pi_( r.pi_ )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
, id_(shared_count_id) , id_(shared_count_id)
#endif #endif

View File

@@ -16,6 +16,7 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
#include <machine/sys/inline.h> #include <machine/sys/inline.h>
namespace boost namespace boost
@@ -71,7 +72,7 @@ inline int atomic_conditional_increment( int * pw )
} }
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -21,6 +21,7 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
#include <builtins.h> #include <builtins.h>
#include <sys/atomic_op.h> #include <sys/atomic_op.h>
@@ -63,7 +64,7 @@ inline int32_t atomic_conditional_increment( int32_t * pw )
} }
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -16,6 +16,8 @@
// http://www.boost.org/LICENSE_1_0.txt // http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
namespace boost namespace boost
@@ -26,17 +28,17 @@ namespace detail
typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t; typedef _Atomic( boost::int_least32_t ) atomic_int_least32_t;
inline void atomic_increment( atomic_int_least32_t * pw ) inline void atomic_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{ {
__c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED ); __c11_atomic_fetch_add( pw, 1, __ATOMIC_RELAXED );
} }
inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw ) inline boost::int_least32_t atomic_decrement( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{ {
return __c11_atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL ); return __c11_atomic_fetch_sub( pw, 1, __ATOMIC_ACQ_REL );
} }
inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw ) inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{ {
// long r = *pw; // long r = *pw;
// if( r != 0 ) ++*pw; // if( r != 0 ) ++*pw;
@@ -63,7 +65,7 @@ inline boost::int_least32_t atomic_conditional_increment( atomic_int_least32_t *
# pragma clang diagnostic ignored "-Wweak-vtables" # pragma clang diagnostic ignored "-Wweak-vtables"
#endif #endif
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:
@@ -75,43 +77,43 @@ private:
public: public:
sp_counted_base() sp_counted_base() BOOST_SP_NOEXCEPT
{ {
__c11_atomic_init( &use_count_, 1 ); __c11_atomic_init( &use_count_, 1 );
__c11_atomic_init( &weak_count_, 1 ); __c11_atomic_init( &weak_count_, 1 );
} }
virtual ~sp_counted_base() // nothrow virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
{ {
} }
// dispose() is called when use_count_ drops to zero, to release // dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this. // the resources managed by *this.
virtual void dispose() = 0; // nothrow virtual void dispose() BOOST_SP_NOEXCEPT = 0; // nothrow
// destroy() is called when weak_count_ drops to zero. // destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow virtual void destroy() BOOST_SP_NOEXCEPT // nothrow
{ {
delete this; delete this;
} }
virtual void * get_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() = 0; virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy() void add_ref_copy() BOOST_SP_NOEXCEPT
{ {
atomic_increment( &use_count_ ); atomic_increment( &use_count_ );
} }
bool add_ref_lock() // true on success bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
{ {
return atomic_conditional_increment( &use_count_ ) != 0; return atomic_conditional_increment( &use_count_ ) != 0;
} }
void release() // nothrow void release() BOOST_SP_NOEXCEPT
{ {
if( atomic_decrement( &use_count_ ) == 1 ) if( atomic_decrement( &use_count_ ) == 1 )
{ {
@@ -120,12 +122,12 @@ public:
} }
} }
void weak_add_ref() // nothrow void weak_add_ref() BOOST_SP_NOEXCEPT
{ {
atomic_increment( &weak_count_ ); atomic_increment( &weak_count_ );
} }
void weak_release() // nothrow void weak_release() BOOST_SP_NOEXCEPT
{ {
if( atomic_decrement( &weak_count_ ) == 1 ) if( atomic_decrement( &weak_count_ ) == 1 )
{ {
@@ -133,7 +135,7 @@ public:
} }
} }
long use_count() const // nothrow long use_count() const BOOST_SP_NOEXCEPT
{ {
return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE ); return __c11_atomic_load( const_cast< atomic_int_least32_t* >( &use_count_ ), __ATOMIC_ACQUIRE );
} }

View File

@@ -25,6 +25,7 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
namespace boost namespace boost
{ {
@@ -91,7 +92,7 @@ store:
return a; return a;
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -26,6 +26,7 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
namespace boost namespace boost
{ {
@@ -79,7 +80,7 @@ inline int atomic_conditional_increment( int * pw )
} }
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -17,6 +17,7 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
namespace boost namespace boost
{ {
@@ -78,7 +79,7 @@ inline int atomic_conditional_increment( int * pw )
return rv; return rv;
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -21,6 +21,7 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
namespace boost namespace boost
{ {
@@ -108,7 +109,7 @@ inline int atomic_conditional_increment( int * pw )
return rv; return rv;
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -25,6 +25,7 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
namespace boost namespace boost
{ {
@@ -102,7 +103,7 @@ inline int atomic_conditional_increment( int * pw )
return rv; return rv;
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -20,6 +20,7 @@
// Thanks to Michael van der Westhuizen // Thanks to Michael van der Westhuizen
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
#include <inttypes.h> // int32_t #include <inttypes.h> // int32_t
namespace boost namespace boost
@@ -87,7 +88,7 @@ inline int32_t atomic_conditional_increment( int32_t * pw )
} }
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -25,6 +25,7 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
namespace boost namespace boost
{ {
@@ -94,7 +95,7 @@ inline int atomic_conditional_increment( int * pw )
return rv; return rv;
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -19,6 +19,9 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
namespace boost namespace boost
{ {
@@ -26,55 +29,55 @@ namespace boost
namespace detail namespace detail
{ {
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:
sp_counted_base( sp_counted_base const & ); sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & ); sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared boost::int_least32_t use_count_; // #shared
long weak_count_; // #weak + (#shared != 0) boost::int_least32_t weak_count_; // #weak + (#shared != 0)
public: public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 )
{ {
} }
virtual ~sp_counted_base() // nothrow virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
{ {
} }
// dispose() is called when use_count_ drops to zero, to release // dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this. // the resources managed by *this.
virtual void dispose() = 0; // nothrow virtual void dispose() BOOST_SP_NOEXCEPT = 0; // nothrow
// destroy() is called when weak_count_ drops to zero. // destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow virtual void destroy() BOOST_SP_NOEXCEPT // nothrow
{ {
delete this; delete this;
} }
virtual void * get_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() = 0; virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy() void add_ref_copy() BOOST_SP_NOEXCEPT
{ {
++use_count_; ++use_count_;
} }
bool add_ref_lock() // true on success bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
{ {
if( use_count_ == 0 ) return false; if( use_count_ == 0 ) return false;
++use_count_; ++use_count_;
return true; return true;
} }
void release() // nothrow void release() BOOST_SP_NOEXCEPT
{ {
if( --use_count_ == 0 ) if( --use_count_ == 0 )
{ {
@@ -83,12 +86,12 @@ public:
} }
} }
void weak_add_ref() // nothrow void weak_add_ref() BOOST_SP_NOEXCEPT
{ {
++weak_count_; ++weak_count_;
} }
void weak_release() // nothrow void weak_release() BOOST_SP_NOEXCEPT
{ {
if( --weak_count_ == 0 ) if( --weak_count_ == 0 )
{ {
@@ -96,7 +99,7 @@ public:
} }
} }
long use_count() const // nothrow long use_count() const BOOST_SP_NOEXCEPT
{ {
return use_count_; return use_count_;
} }

View File

@@ -20,6 +20,8 @@
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
#include <pthread.h> #include <pthread.h>
namespace boost namespace boost
@@ -28,15 +30,15 @@ namespace boost
namespace detail namespace detail
{ {
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:
sp_counted_base( sp_counted_base const & ); sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & ); sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared boost::int_least32_t use_count_; // #shared
long weak_count_; // #weak + (#shared != 0) boost::int_least32_t weak_count_; // #weak + (#shared != 0)
mutable pthread_mutex_t m_; mutable pthread_mutex_t m_;
@@ -92,7 +94,7 @@ public:
void release() // nothrow void release() // nothrow
{ {
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
long new_use_count = --use_count_; boost::int_least32_t new_use_count = --use_count_;
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
if( new_use_count == 0 ) if( new_use_count == 0 )
@@ -112,7 +114,7 @@ public:
void weak_release() // nothrow void weak_release() // nothrow
{ {
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
long new_weak_count = --weak_count_; boost::int_least32_t new_weak_count = --weak_count_;
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
if( new_weak_count == 0 ) if( new_weak_count == 0 )
@@ -124,7 +126,7 @@ public:
long use_count() const // nothrow long use_count() const // nothrow
{ {
BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 ); BOOST_VERIFY( pthread_mutex_lock( &m_ ) == 0 );
long r = use_count_; boost::int_least32_t r = use_count_;
BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 ); BOOST_VERIFY( pthread_mutex_unlock( &m_ ) == 0 );
return r; return r;

View File

@@ -20,6 +20,7 @@
// Thanks to Michael van der Westhuizen // Thanks to Michael van der Westhuizen
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
#include <inttypes.h> // uint32_t #include <inttypes.h> // uint32_t
namespace boost namespace boost
@@ -82,7 +83,7 @@ inline uint32_t atomic_conditional_increment( uint32_t * pw )
} }
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -21,6 +21,7 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
#include <atomic.h> #include <atomic.h>
namespace boost namespace boost
@@ -29,7 +30,7 @@ namespace boost
namespace detail namespace detail
{ {
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -20,6 +20,7 @@
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/spinlock_pool.hpp> #include <boost/smart_ptr/detail/spinlock_pool.hpp>
#include <boost/config.hpp>
namespace boost namespace boost
{ {
@@ -51,7 +52,7 @@ inline int atomic_conditional_increment( int * pw )
return rv; return rv;
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -16,6 +16,8 @@
// http://www.boost.org/LICENSE_1_0.txt // http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/config.hpp>
#include <atomic> #include <atomic>
#include <cstdint> #include <cstdint>
@@ -25,17 +27,17 @@ namespace boost
namespace detail namespace detail
{ {
inline void atomic_increment( std::atomic_int_least32_t * pw ) inline void atomic_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{ {
pw->fetch_add( 1, std::memory_order_relaxed ); pw->fetch_add( 1, std::memory_order_relaxed );
} }
inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw ) inline std::int_least32_t atomic_decrement( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{ {
return pw->fetch_sub( 1, std::memory_order_acq_rel ); return pw->fetch_sub( 1, std::memory_order_acq_rel );
} }
inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw ) inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_t * pw ) BOOST_SP_NOEXCEPT
{ {
// long r = *pw; // long r = *pw;
// if( r != 0 ) ++*pw; // if( r != 0 ) ++*pw;
@@ -57,7 +59,7 @@ inline std::int_least32_t atomic_conditional_increment( std::atomic_int_least32_
} }
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:
@@ -69,41 +71,41 @@ private:
public: public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 ) sp_counted_base() BOOST_SP_NOEXCEPT: use_count_( 1 ), weak_count_( 1 )
{ {
} }
virtual ~sp_counted_base() // nothrow virtual ~sp_counted_base() /*BOOST_SP_NOEXCEPT*/
{ {
} }
// dispose() is called when use_count_ drops to zero, to release // dispose() is called when use_count_ drops to zero, to release
// the resources managed by *this. // the resources managed by *this.
virtual void dispose() = 0; // nothrow virtual void dispose() BOOST_SP_NOEXCEPT = 0;
// destroy() is called when weak_count_ drops to zero. // destroy() is called when weak_count_ drops to zero.
virtual void destroy() // nothrow virtual void destroy() BOOST_SP_NOEXCEPT
{ {
delete this; delete this;
} }
virtual void * get_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT = 0;
virtual void * get_untyped_deleter() = 0; virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT = 0;
void add_ref_copy() void add_ref_copy() BOOST_SP_NOEXCEPT
{ {
atomic_increment( &use_count_ ); atomic_increment( &use_count_ );
} }
bool add_ref_lock() // true on success bool add_ref_lock() BOOST_SP_NOEXCEPT // true on success
{ {
return atomic_conditional_increment( &use_count_ ) != 0; return atomic_conditional_increment( &use_count_ ) != 0;
} }
void release() // nothrow void release() BOOST_SP_NOEXCEPT
{ {
if( atomic_decrement( &use_count_ ) == 1 ) if( atomic_decrement( &use_count_ ) == 1 )
{ {
@@ -112,12 +114,12 @@ public:
} }
} }
void weak_add_ref() // nothrow void weak_add_ref() BOOST_SP_NOEXCEPT
{ {
atomic_increment( &weak_count_ ); atomic_increment( &weak_count_ );
} }
void weak_release() // nothrow void weak_release() BOOST_SP_NOEXCEPT
{ {
if( atomic_decrement( &weak_count_ ) == 1 ) if( atomic_decrement( &weak_count_ ) == 1 )
{ {
@@ -125,7 +127,7 @@ public:
} }
} }
long use_count() const // nothrow long use_count() const BOOST_SP_NOEXCEPT
{ {
return use_count_.load( std::memory_order_acquire ); return use_count_.load( std::memory_order_acquire );
} }

View File

@@ -16,6 +16,7 @@
// http://www.boost.org/LICENSE_1_0.txt // http://www.boost.org/LICENSE_1_0.txt
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
#include <limits.h> #include <limits.h>
#if defined( __ia64__ ) && defined( __INTEL_COMPILER ) #if defined( __ia64__ ) && defined( __INTEL_COMPILER )
@@ -76,7 +77,7 @@ inline sp_int32_t atomic_conditional_increment( sp_int32_t * pw )
} }
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -22,6 +22,7 @@
// //
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
extern "builtin" void __lwsync(void); extern "builtin" void __lwsync(void);
extern "builtin" void __isync(void); extern "builtin" void __isync(void);
@@ -70,7 +71,7 @@ inline int atomic_conditional_increment( int *pw )
} }
} }
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -27,6 +27,7 @@
#include <boost/smart_ptr/detail/sp_interlocked.hpp> #include <boost/smart_ptr/detail/sp_interlocked.hpp>
#include <boost/detail/workaround.hpp> #include <boost/detail/workaround.hpp>
#include <boost/detail/sp_typeinfo.hpp> #include <boost/detail/sp_typeinfo.hpp>
#include <boost/config.hpp>
namespace boost namespace boost
{ {
@@ -34,7 +35,7 @@ namespace boost
namespace detail namespace detail
{ {
class sp_counted_base class BOOST_SYMBOL_VISIBLE sp_counted_base
{ {
private: private:

View File

@@ -26,6 +26,7 @@
#include <boost/checked_delete.hpp> #include <boost/checked_delete.hpp>
#include <boost/smart_ptr/detail/sp_counted_base.hpp> #include <boost/smart_ptr/detail/sp_counted_base.hpp>
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
#include <boost/core/addressof.hpp> #include <boost/core/addressof.hpp>
#if defined(BOOST_SP_USE_QUICK_ALLOCATOR) #if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
@@ -55,16 +56,16 @@ namespace detail
template<class D> class local_sp_deleter; template<class D> class local_sp_deleter;
template<class D> D * get_local_deleter( D * /*p*/ ) template<class D> D * get_local_deleter( D * /*p*/ ) BOOST_SP_NOEXCEPT
{ {
return 0; return 0;
} }
template<class D> D * get_local_deleter( local_sp_deleter<D> * p ); template<class D> D * get_local_deleter( local_sp_deleter<D> * p ) BOOST_SP_NOEXCEPT;
// //
template<class X> class sp_counted_impl_p: public sp_counted_base template<class X> class BOOST_SYMBOL_VISIBLE sp_counted_impl_p: public sp_counted_base
{ {
private: private:
@@ -84,7 +85,7 @@ public:
#endif #endif
} }
virtual void dispose() // nothrow virtual void dispose() BOOST_SP_NOEXCEPT
{ {
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_destructor_hook( px_, sizeof(X), this ); boost::sp_scalar_destructor_hook( px_, sizeof(X), this );
@@ -92,17 +93,17 @@ public:
boost::checked_delete( px_ ); boost::checked_delete( px_ );
} }
virtual void * get_deleter( sp_typeinfo const & ) virtual void * get_deleter( sp_typeinfo const & ) BOOST_SP_NOEXCEPT
{ {
return 0; return 0;
} }
virtual void * get_local_deleter( sp_typeinfo const & ) virtual void * get_local_deleter( sp_typeinfo const & ) BOOST_SP_NOEXCEPT
{ {
return 0; return 0;
} }
virtual void * get_untyped_deleter() virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT
{ {
return 0; return 0;
} }
@@ -143,7 +144,7 @@ public:
# pragma option push -Vx- # pragma option push -Vx-
#endif #endif
template<class P, class D> class sp_counted_impl_pd: public sp_counted_base template<class P, class D> class BOOST_SYMBOL_VISIBLE sp_counted_impl_pd: public sp_counted_base
{ {
private: private:
@@ -167,22 +168,22 @@ public:
{ {
} }
virtual void dispose() // nothrow virtual void dispose() BOOST_SP_NOEXCEPT
{ {
del( ptr ); del( ptr );
} }
virtual void * get_deleter( sp_typeinfo const & ti ) virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
{ {
return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0; return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0;
} }
virtual void * get_local_deleter( sp_typeinfo const & ti ) virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
{ {
return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0; return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0;
} }
virtual void * get_untyped_deleter() virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT
{ {
return &reinterpret_cast<char&>( del ); return &reinterpret_cast<char&>( del );
} }
@@ -216,7 +217,7 @@ public:
#endif #endif
}; };
template<class P, class D, class A> class sp_counted_impl_pda: public sp_counted_base template<class P, class D, class A> class BOOST_SYMBOL_VISIBLE sp_counted_impl_pda: public sp_counted_base
{ {
private: private:
@@ -241,12 +242,12 @@ public:
{ {
} }
virtual void dispose() // nothrow virtual void dispose() BOOST_SP_NOEXCEPT
{ {
d_( p_ ); d_( p_ );
} }
virtual void destroy() // nothrow virtual void destroy() BOOST_SP_NOEXCEPT
{ {
#if !defined( BOOST_NO_CXX11_ALLOCATOR ) #if !defined( BOOST_NO_CXX11_ALLOCATOR )
@@ -265,17 +266,17 @@ public:
a2.deallocate( this, 1 ); a2.deallocate( this, 1 );
} }
virtual void * get_deleter( sp_typeinfo const & ti ) virtual void * get_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
{ {
return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0; return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0;
} }
virtual void * get_local_deleter( sp_typeinfo const & ti ) virtual void * get_local_deleter( sp_typeinfo const & ti ) BOOST_SP_NOEXCEPT
{ {
return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0; return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0;
} }
virtual void * get_untyped_deleter() virtual void * get_untyped_deleter() BOOST_SP_NOEXCEPT
{ {
return &reinterpret_cast<char&>( d_ ); return &reinterpret_cast<char&>( d_ );
} }

View File

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

View File

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

View File

@@ -25,7 +25,7 @@
// //
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/predef.h> #include <boost/predef/platform/windows_runtime.h>
#if BOOST_PLAT_WINDOWS_RUNTIME #if BOOST_PLAT_WINDOWS_RUNTIME
#include <thread> #include <thread>
@@ -60,19 +60,25 @@ namespace detail
{ {
#if !defined( BOOST_USE_WINDOWS_H ) && !BOOST_PLAT_WINDOWS_RUNTIME #if !defined( BOOST_USE_WINDOWS_H ) && !BOOST_PLAT_WINDOWS_RUNTIME
#if !BOOST_COMP_CLANG || !defined __MINGW32__
extern "C" void __stdcall Sleep( unsigned long ms ); #if defined(__clang__) && defined(__x86_64__)
// clang x64 warns that __stdcall is ignored
# define BOOST_SP_STDCALL
#else #else
#include <_mingw.h> # define BOOST_SP_STDCALL __stdcall
#if !defined __MINGW64_VERSION_MAJOR
extern "C" void __stdcall Sleep( unsigned long ms );
#else
extern "C" __declspec(dllimport) void __stdcall Sleep( unsigned long ms );
#endif
#endif
#endif #endif
inline void yield( unsigned k ) #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 ) && !BOOST_PLAT_WINDOWS_RUNTIME
inline void yield( unsigned k ) BOOST_NOEXCEPT
{ {
if( k < 4 ) if( k < 4 )
{ {

View File

@@ -144,8 +144,7 @@ template<typename T>
boost::weak_ptr<T> weak_from_raw(T *p) boost::weak_ptr<T> weak_from_raw(T *p)
{ {
BOOST_ASSERT(p != 0); BOOST_ASSERT(p != 0);
boost::weak_ptr<T> result; boost::weak_ptr<T> result(p->enable_shared_from_raw::weak_from_this(), p);
result._internal_aliasing_assign(p->enable_shared_from_raw::weak_from_this(), p);
return result; return result;
} }

View File

@@ -297,6 +297,8 @@ template<class T> T * get_pointer(intrusive_ptr<T> const & p) BOOST_SP_NOEXCEPT
return p.get(); return p.get();
} }
// pointer casts
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p) template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
{ {
return static_cast<T *>(p.get()); return static_cast<T *>(p.get());
@@ -312,6 +314,31 @@ template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U
return dynamic_cast<T *>(p.get()); return dynamic_cast<T *>(p.get());
} }
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class T, class U> intrusive_ptr<T> static_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
{
return intrusive_ptr<T>( static_cast<T*>( p.detach() ), false );
}
template<class T, class U> intrusive_ptr<T> const_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
{
return intrusive_ptr<T>( const_cast<T*>( p.detach() ), false );
}
template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
{
T * p2 = dynamic_cast<T*>( p.get() );
intrusive_ptr<T> r( p2, false );
if( p2 ) p.detach();
return r;
}
#endif // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
// operator<< // operator<<
#if !defined(BOOST_NO_IOSTREAM) #if !defined(BOOST_NO_IOSTREAM)

View File

@@ -1,6 +1,6 @@
/* /*
Copyright 2017 Peter Dimov Copyright 2017 Peter Dimov
Copyright 2017 Glen Joseph Fernandes Copyright 2017-2019 Glen Joseph Fernandes
(glenjofe@gmail.com) (glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
@@ -14,7 +14,8 @@ Distributed under the Boost Software License, Version 1.0.
namespace boost { namespace boost {
template<class T> template<class T>
inline typename detail::lsp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared() make_local_shared()
{ {
return boost::allocate_local_shared<T>(std::allocator<typename return boost::allocate_local_shared<T>(std::allocator<typename
@@ -22,15 +23,17 @@ make_local_shared()
} }
template<class T> template<class T>
inline typename detail::lsp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value,
make_local_shared(const typename detail::sp_array_element<T>::type& value) local_shared_ptr<T> >::type
make_local_shared(const typename remove_extent<T>::type& value)
{ {
return boost::allocate_local_shared<T>(std::allocator<typename return boost::allocate_local_shared<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), value); detail::sp_array_scalar<T>::type>(), value);
} }
template<class T> template<class T>
inline typename detail::lsp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared(std::size_t size) make_local_shared(std::size_t size)
{ {
return boost::allocate_local_shared<T>(std::allocator<typename return boost::allocate_local_shared<T>(std::allocator<typename
@@ -38,27 +41,30 @@ make_local_shared(std::size_t size)
} }
template<class T> template<class T>
inline typename detail::lsp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared(std::size_t size, make_local_shared(std::size_t size,
const typename detail::sp_array_element<T>::type& value) const typename remove_extent<T>::type& value)
{ {
return boost::allocate_local_shared<T>(std::allocator<typename return boost::allocate_local_shared<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), size, value); detail::sp_array_scalar<T>::type>(), size, value);
} }
template<class T> template<class T>
inline typename detail::lsp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared_noinit() make_local_shared_noinit()
{ {
return allocate_local_shared_noinit<T>(std::allocator<typename return boost::allocate_local_shared_noinit<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>()); detail::sp_array_scalar<T>::type>());
} }
template<class T> template<class T>
inline typename detail::lsp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type
make_local_shared_noinit(std::size_t size) make_local_shared_noinit(std::size_t size)
{ {
return allocate_local_shared_noinit<T>(std::allocator<typename return boost::allocate_local_shared_noinit<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), size); detail::sp_array_scalar<T>::type>(), size);
} }

View File

@@ -13,6 +13,7 @@
#include <boost/smart_ptr/local_shared_ptr.hpp> #include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/smart_ptr/make_shared.hpp> #include <boost/smart_ptr/make_shared.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <utility> #include <utility>
#include <cstddef> #include <cstddef>
@@ -186,12 +187,14 @@ template<class T, class A> typename boost::detail::lsp_if_not_array<T>::type all
template<class T, class... Args> typename boost::detail::lsp_if_not_array<T>::type make_local_shared( Args&&... args ) 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)... ); typedef typename boost::remove_const<T>::type T2;
return boost::allocate_local_shared<T2>( std::allocator<T2>(), std::forward<Args>(args)... );
} }
template<class T> typename boost::detail::lsp_if_not_array<T>::type make_local_shared_noinit() 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>() ); typedef typename boost::remove_const<T>::type T2;
return boost::allocate_shared_noinit<T2>( std::allocator<T2>() );
} }
} // namespace boost } // namespace boost

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012-2017 Glen Joseph Fernandes Copyright 2012-2019 Glen Joseph Fernandes
(glenjofe@gmail.com) (glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
@@ -13,7 +13,7 @@ Distributed under the Boost Software License, Version 1.0.
namespace boost { namespace boost {
template<class T> template<class T>
inline typename detail::sp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared() make_shared()
{ {
return boost::allocate_shared<T>(std::allocator<typename return boost::allocate_shared<T>(std::allocator<typename
@@ -21,15 +21,15 @@ make_shared()
} }
template<class T> template<class T>
inline typename detail::sp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared(const typename detail::sp_array_element<T>::type& value) make_shared(const typename remove_extent<T>::type& value)
{ {
return boost::allocate_shared<T>(std::allocator<typename return boost::allocate_shared<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), value); detail::sp_array_scalar<T>::type>(), value);
} }
template<class T> template<class T>
inline typename detail::sp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared(std::size_t size) make_shared(std::size_t size)
{ {
return boost::allocate_shared<T>(std::allocator<typename return boost::allocate_shared<T>(std::allocator<typename
@@ -37,27 +37,26 @@ make_shared(std::size_t size)
} }
template<class T> template<class T>
inline typename detail::sp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared(std::size_t size, make_shared(std::size_t size, const typename remove_extent<T>::type& value)
const typename detail::sp_array_element<T>::type& value)
{ {
return boost::allocate_shared<T>(std::allocator<typename return boost::allocate_shared<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), size, value); detail::sp_array_scalar<T>::type>(), size, value);
} }
template<class T> template<class T>
inline typename detail::sp_if_size_array<T>::type inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared_noinit() make_shared_noinit()
{ {
return allocate_shared_noinit<T>(std::allocator<typename return boost::allocate_shared_noinit<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>()); detail::sp_array_scalar<T>::type>());
} }
template<class T> template<class T>
inline typename detail::sp_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared_noinit(std::size_t size) make_shared_noinit(std::size_t size)
{ {
return allocate_shared_noinit<T>(std::allocator<typename return boost::allocate_shared_noinit<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), size); detail::sp_array_scalar<T>::type>(), size);
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2012-2015 Glen Joseph Fernandes Copyright 2012-2019 Glen Joseph Fernandes
(glenjofe@gmail.com) (glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
@@ -8,59 +8,18 @@ Distributed under the Boost Software License, Version 1.0.
#ifndef BOOST_SMART_PTR_MAKE_UNIQUE_HPP #ifndef BOOST_SMART_PTR_MAKE_UNIQUE_HPP
#define BOOST_SMART_PTR_MAKE_UNIQUE_HPP #define BOOST_SMART_PTR_MAKE_UNIQUE_HPP
#include <boost/config.hpp> #include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/is_array.hpp>
#include <boost/type_traits/is_unbounded_array.hpp>
#include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <memory> #include <memory>
#include <utility> #include <utility>
namespace boost { namespace boost {
namespace detail {
template<class T> template<class T>
struct up_if_object { inline typename enable_if_<!is_array<T>::value, std::unique_ptr<T> >::type
typedef std::unique_ptr<T> type;
};
template<class T>
struct up_if_object<T[]> { };
template<class T, std::size_t N>
struct up_if_object<T[N]> { };
template<class T>
struct up_if_array { };
template<class T>
struct up_if_array<T[]> {
typedef std::unique_ptr<T[]> type;
};
template<class T>
struct up_remove_reference {
typedef T type;
};
template<class T>
struct up_remove_reference<T&> {
typedef T type;
};
template<class T>
struct up_remove_reference<T&&> {
typedef T type;
};
template<class T>
struct up_element { };
template<class T>
struct up_element<T[]> {
typedef T type;
};
} /* detail */
template<class T>
inline typename detail::up_if_object<T>::type
make_unique() make_unique()
{ {
return std::unique_ptr<T>(new T()); return std::unique_ptr<T>(new T());
@@ -68,7 +27,7 @@ make_unique()
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template<class T, class... Args> template<class T, class... Args>
inline typename detail::up_if_object<T>::type inline typename enable_if_<!is_array<T>::value, std::unique_ptr<T> >::type
make_unique(Args&&... args) make_unique(Args&&... args)
{ {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
@@ -76,33 +35,33 @@ make_unique(Args&&... args)
#endif #endif
template<class T> template<class T>
inline typename detail::up_if_object<T>::type inline typename enable_if_<!is_array<T>::value, std::unique_ptr<T> >::type
make_unique(typename detail::up_remove_reference<T>::type&& value) make_unique(typename remove_reference<T>::type&& value)
{ {
return std::unique_ptr<T>(new T(std::move(value))); return std::unique_ptr<T>(new T(std::move(value)));
} }
template<class T> template<class T>
inline typename detail::up_if_object<T>::type inline typename enable_if_<!is_array<T>::value, std::unique_ptr<T> >::type
make_unique_noinit() make_unique_noinit()
{ {
return std::unique_ptr<T>(new T); return std::unique_ptr<T>(new T);
} }
template<class T> template<class T>
inline typename detail::up_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value,
std::unique_ptr<T> >::type
make_unique(std::size_t size) make_unique(std::size_t size)
{ {
return std::unique_ptr<T>(new typename return std::unique_ptr<T>(new typename remove_extent<T>::type[size]());
detail::up_element<T>::type[size]());
} }
template<class T> template<class T>
inline typename detail::up_if_array<T>::type inline typename enable_if_<is_unbounded_array<T>::value,
std::unique_ptr<T> >::type
make_unique_noinit(std::size_t size) make_unique_noinit(std::size_t size)
{ {
return std::unique_ptr<T>(new typename return std::unique_ptr<T>(new typename remove_extent<T>::type[size]);
detail::up_element<T>::type[size]);
} }
} /* boost */ } /* boost */

View File

@@ -797,7 +797,7 @@ public:
return px == r.px && pn == r.pn; return px == r.px && pn == r.pn;
} }
boost::detail::shared_count _internal_count() const BOOST_NOEXCEPT boost::detail::shared_count _internal_count() const BOOST_SP_NOEXCEPT
{ {
return pn; return pn;
} }
@@ -1022,7 +1022,7 @@ private:
public: public:
esft2_deleter_wrapper() esft2_deleter_wrapper() BOOST_SP_NOEXCEPT
{ {
} }

View File

@@ -137,6 +137,23 @@ public:
boost::detail::sp_assert_convertible< Y, T >(); boost::detail::sp_assert_convertible< Y, T >();
} }
// aliasing
template<class Y> weak_ptr(shared_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( r.pn )
{
}
template<class Y> weak_ptr(weak_ptr<Y> const & r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( r.pn )
{
}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template<class Y> weak_ptr(weak_ptr<Y> && r, element_type * p) BOOST_SP_NOEXCEPT: px( p ), pn( std::move( r.pn ) )
{
}
#endif
#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300)
template<class Y> template<class Y>
@@ -194,6 +211,11 @@ public:
return pn.empty(); return pn.empty();
} }
bool empty() const BOOST_SP_NOEXCEPT // extension, not in std::weak_ptr
{
return pn.empty();
}
void reset() BOOST_SP_NOEXCEPT void reset() BOOST_SP_NOEXCEPT
{ {
this_type().swap(*this); this_type().swap(*this);
@@ -205,13 +227,6 @@ public:
pn.swap(other.pn); pn.swap(other.pn);
} }
template<typename Y>
void _internal_aliasing_assign(weak_ptr<Y> const & r, element_type * px2) BOOST_SP_NOEXCEPT
{
px = px2;
pn = r.pn;
}
template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT
{ {
return pn < rhs.pn; return pn < rhs.pn;

View File

@@ -7,19 +7,25 @@
# accompanying file LICENSE_1_0.txt or copy at # accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt) # http://www.boost.org/LICENSE_1_0.txt)
# bring in rules for testing
import testing ; import testing ;
project
: requirements
<toolset>gcc:<cxxflags>-Wno-non-virtual-dtor
<toolset>gcc:<cxxflags>-Wno-deprecated-declarations
#<toolset>gcc:<cxxflags>-Wno-delete-non-virtual-dtor (not in 4.4/4.6)
;
# quick test (for CI) # quick test (for CI)
run quick.cpp ; run quick.cpp ;
# full test suite # full test suite
run smart_ptr_test.cpp ; run smart_ptr_test.cpp ;
run shared_ptr_basic_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ; run shared_ptr_basic_test.cpp ;
run shared_ptr_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ; run shared_ptr_test.cpp ;
run weak_ptr_test.cpp ; run weak_ptr_test.cpp ;
run weak_ptr_move_test.cpp ; run weak_ptr_move_test.cpp ;
run shared_from_this_test.cpp : : : <toolset>gcc:<cxxflags>-Wno-non-virtual-dtor ; run shared_from_this_test.cpp ;
run get_deleter_test.cpp ; run get_deleter_test.cpp ;
run intrusive_ptr_test.cpp ; run intrusive_ptr_test.cpp ;
run intrusive_ptr_move_test.cpp ; run intrusive_ptr_move_test.cpp ;
@@ -152,18 +158,18 @@ compile-fail array_fail_dereference.cpp ;
compile-fail array_fail_member_access.cpp ; compile-fail array_fail_member_access.cpp ;
compile-fail array_fail_array_access.cpp ; compile-fail array_fail_array_access.cpp ;
run make_shared_array_test.cpp ; run make_shared_array_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run make_shared_arrays_test.cpp ; # <cxxflags>-fno-deduce-init-list no longer needed for gcc-4.6 run make_shared_arrays_test.cpp ; # <cxxflags>-fno-deduce-init-list no longer needed for gcc-4.6
run make_shared_array_throws_test.cpp ; run make_shared_array_throws_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run make_shared_array_esft_test.cpp ; run make_shared_array_esft_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run make_shared_array_noinit_test.cpp ; run make_shared_array_noinit_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run make_shared_array_value_test.cpp ; run make_shared_array_value_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run allocate_shared_array_test.cpp ; run allocate_shared_array_test.cpp ;
run allocate_shared_arrays_test.cpp ; # <cxxflags>-fno-deduce-init-list no longer needed for gcc-4.6 run allocate_shared_arrays_test.cpp ; # <cxxflags>-fno-deduce-init-list no longer needed for gcc-4.6
run allocate_shared_array_throws_test.cpp ; run allocate_shared_array_throws_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run allocate_shared_array_esft_test.cpp ; run allocate_shared_array_esft_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run allocate_shared_array_noinit_test.cpp ; run allocate_shared_array_noinit_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run allocate_shared_array_value_test.cpp ; run allocate_shared_array_value_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run allocate_shared_array_construct_test.cpp ; run allocate_shared_array_construct_test.cpp ;
run make_unique_test.cpp ; run make_unique_test.cpp ;
@@ -230,7 +236,7 @@ run shared_ptr_fn_test.cpp ;
run get_deleter_test2.cpp ; run get_deleter_test2.cpp ;
run get_deleter_test3.cpp ; run get_deleter_test3.cpp ;
run get_deleter_array_test2.cpp ; run get_deleter_array_test2.cpp ;
run get_deleter_array_test3.cpp ; run get_deleter_array_test3.cpp : : : <toolset>msvc-8.0:<build>no ;
run sp_convertible_test2.cpp ; run sp_convertible_test2.cpp ;
@@ -269,6 +275,37 @@ run local_sp_fn_test.cpp ;
run lsp_convertible_test.cpp ; run lsp_convertible_test.cpp ;
run lsp_convertible_test2.cpp ; run lsp_convertible_test2.cpp ;
run make_shared_array_tmp_test.cpp ; run make_shared_array_tmp_test.cpp : : : <toolset>msvc-8.0:<build>no ;
run lw_thread_test.cpp : : : <threading>multi ; run lw_thread_test.cpp : : : <threading>multi ;
compile sp_windows_h_test.cpp ;
compile spinlock_windows_h_test.cpp ;
compile yield_k_windows_h_test.cpp ;
lib dll_test : dll_test_lib.cpp : <link>shared:<define>DLL_TEST_DYN_LINK=1 ;
explicit dll_test ;
run dll_test_main.cpp dll_test : : : <link>static : dll_test_static ;
run dll_test_main.cpp dll_test : : : <link>shared : dll_test_shared ;
run make_shared_const_test.cpp ;
run make_local_shared_const_test.cpp ;
lib abi_test_mt : abi_test_lib.cpp : <link>static ;
explicit abi_test_mt ;
obj abi_test_lib_nt : abi_test_lib.cpp : <define>BOOST_DISABLE_THREADS ;
explicit abi_test_lib_nt ;
lib abi_test_nt : abi_test_lib_nt : <link>static ;
explicit abi_test_nt ;
run abi_test_main.cpp abi_test_mt : : : <define>BOOST_DISABLE_THREADS : abi_test_nt_mt ;
run abi_test_main.cpp abi_test_nt : : : : abi_test_mt_nt ;
run abi_test_main.cpp abi_test_mt/<cxxstd>0x : : : <cxxstd>98 : abi_test_03_11 ;
run abi_test_main.cpp abi_test_mt/<cxxstd>98 : : : <cxxstd>0x : abi_test_11_03 ;
run weak_ptr_alias_test.cpp ;
run weak_ptr_alias_move_test.cpp ;

43
test/abi_test_lib.cpp Normal file
View File

@@ -0,0 +1,43 @@
// Copyright 2018 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
//
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config/pragma_message.hpp>
#if defined(BOOST_DISABLE_THREADS)
BOOST_PRAGMA_MESSAGE( "BOOST_DISABLE_THREADS is defined" )
#else
BOOST_PRAGMA_MESSAGE( "BOOST_DISABLE_THREADS is not defined" )
#endif
#if defined(BOOST_NO_CXX11_HDR_ATOMIC)
BOOST_PRAGMA_MESSAGE( "BOOST_NO_CXX11_HDR_ATOMIC is defined" )
#else
BOOST_PRAGMA_MESSAGE( "BOOST_NO_CXX11_HDR_ATOMIC is not defined" )
#endif
void abi_test_1( boost::shared_ptr<void> & p )
{
BOOST_TEST_EQ( p.use_count(), 1 );
p.reset();
BOOST_TEST_EQ( p.use_count(), 0 );
}
boost::shared_ptr<void> abi_test_2( boost::shared_ptr<void> const & p )
{
BOOST_TEST_EQ( p.use_count(), 1 );
return p;
}
boost::shared_ptr<void> abi_test_3()
{
return boost::shared_ptr<void>( static_cast<int*>( 0 ) );
}

82
test/abi_test_main.cpp Normal file
View File

@@ -0,0 +1,82 @@
// Copyright 2018 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
//
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config/pragma_message.hpp>
#if defined(BOOST_DISABLE_THREADS)
BOOST_PRAGMA_MESSAGE( "BOOST_DISABLE_THREADS is defined" )
#else
BOOST_PRAGMA_MESSAGE( "BOOST_DISABLE_THREADS is not defined" )
#endif
#if defined(BOOST_NO_CXX11_HDR_ATOMIC)
BOOST_PRAGMA_MESSAGE( "BOOST_NO_CXX11_HDR_ATOMIC is defined" )
#else
BOOST_PRAGMA_MESSAGE( "BOOST_NO_CXX11_HDR_ATOMIC is not defined" )
#endif
void abi_test_1( boost::shared_ptr<void> & p );
boost::shared_ptr<void> abi_test_2( boost::shared_ptr<void> const & p );
boost::shared_ptr<void> abi_test_3();
static int deleter_called;
void deleter( void* )
{
++deleter_called;
}
int main()
{
{
deleter_called = 0;
boost::shared_ptr<void> p( static_cast<void*>( 0 ), deleter );
BOOST_TEST_EQ( p.use_count(), 1 );
abi_test_1( p );
BOOST_TEST_EQ( p.use_count(), 0 );
BOOST_TEST_EQ( deleter_called, 1 );
}
{
deleter_called = 0;
boost::shared_ptr<void> p1( static_cast<void*>( 0 ), deleter );
BOOST_TEST_EQ( p1.use_count(), 1 );
boost::shared_ptr<void> p2 = abi_test_2( p1 );
BOOST_TEST_EQ( p1.use_count(), 2 );
BOOST_TEST_EQ( p2.use_count(), 2 );
p1.reset();
BOOST_TEST_EQ( p2.use_count(), 1 );
p2.reset();
BOOST_TEST_EQ( deleter_called, 1 );
}
{
boost::shared_ptr<void> p = abi_test_3();
BOOST_TEST_EQ( p.use_count(), 1 );
p.reset();
BOOST_TEST_EQ( p.use_count(), 0 );
}
return boost::report_errors();
}

View File

@@ -18,10 +18,10 @@
BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_NO_CXX11_CONSTEXPR") BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_NO_CXX11_CONSTEXPR")
int main() {} int main() {}
#elif BOOST_WORKAROUND( BOOST_MSVC, < 1920 ) #elif BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
// MSVC does not implement static initialization for constexpr // MSVC does not implement static initialization for constexpr constructors
BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_MSVC < 1920") BOOST_PRAGMA_MESSAGE("Skipping test due to BOOST_MSVC < 1930")
int main() {} int main() {}
#elif defined(__clang__) && defined( BOOST_NO_CXX14_CONSTEXPR ) #elif defined(__clang__) && defined( BOOST_NO_CXX14_CONSTEXPR )

View File

@@ -0,0 +1,25 @@
# Copyright 2018, 2019 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt
cmake_minimum_required(VERSION 3.5)
project(cmake_subdir_test LANGUAGES CXX)
add_subdirectory(../.. boostorg/smart_ptr)
add_subdirectory(../../../assert boostorg/assert)
add_subdirectory(../../../config boostorg/config)
add_subdirectory(../../../core boostorg/core)
add_subdirectory(../../../move boostorg/move)
add_subdirectory(../../../predef boostorg/predef)
add_subdirectory(../../../static_assert boostorg/static_assert)
add_subdirectory(../../../throw_exception boostorg/throw_exception)
add_subdirectory(../../../type_traits boostorg/type_traits)
add_executable(quick ../quick.cpp)
target_link_libraries(quick Boost::smart_ptr Boost::core)
enable_testing()
add_test(quick quick)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $<CONFIG>)

42
test/dll_test_lib.cpp Normal file
View File

@@ -0,0 +1,42 @@
// Copyright 2018 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
//
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/config.hpp>
#include <memory>
#if defined(DLL_TEST_DYN_LINK)
# define EXPORT BOOST_SYMBOL_EXPORT
#else
# define EXPORT
#endif
EXPORT boost::shared_ptr<int> dll_test_41()
{
return boost::shared_ptr<int>( new int( 41 ) );
}
EXPORT boost::shared_ptr<int> dll_test_42()
{
return boost::make_shared<int>( 42 );
}
EXPORT boost::shared_ptr<int> dll_test_43()
{
return boost::allocate_shared<int>( std::allocator<int>(), 43 );
}
EXPORT boost::shared_ptr<int[]> dll_test_44()
{
return boost::make_shared<int[1]>( 44 );
}
EXPORT boost::shared_ptr<int[]> dll_test_45()
{
return boost::allocate_shared<int[1]>( std::allocator<int>(), 45 );
}

45
test/dll_test_main.cpp Normal file
View File

@@ -0,0 +1,45 @@
// Copyright 2018 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
//
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/shared_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
boost::shared_ptr<int> dll_test_41();
boost::shared_ptr<int> dll_test_42();
boost::shared_ptr<int> dll_test_43();
boost::shared_ptr<int[]> dll_test_44();
boost::shared_ptr<int[]> dll_test_45();
int main()
{
{
boost::shared_ptr<int> p = dll_test_41();
BOOST_TEST_EQ( *p, 41 );
}
{
boost::shared_ptr<int> p = dll_test_42();
BOOST_TEST_EQ( *p, 42 );
}
{
boost::shared_ptr<int> p = dll_test_43();
BOOST_TEST_EQ( *p, 43 );
}
{
boost::shared_ptr<int[]> p = dll_test_44();
BOOST_TEST_EQ( p[0], 44 );
}
{
boost::shared_ptr<int[]> p = dll_test_45();
BOOST_TEST_EQ( p[0], 45 );
}
return boost::report_errors();
}

View File

@@ -41,7 +41,7 @@ class base
{ {
private: private:
boost::detail::atomic_count use_count_; mutable boost::detail::atomic_count use_count_;
base(base const &); base(base const &);
base & operator=(base const &); base & operator=(base const &);
@@ -69,24 +69,24 @@ public:
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
inline friend void intrusive_ptr_add_ref(base * p) inline friend void intrusive_ptr_add_ref(base const * p)
{ {
++p->use_count_; ++p->use_count_;
} }
inline friend void intrusive_ptr_release(base * p) inline friend void intrusive_ptr_release(base const * p)
{ {
if(--p->use_count_ == 0) delete p; if(--p->use_count_ == 0) delete p;
} }
#else #else
void add_ref() void add_ref() const
{ {
++use_count_; ++use_count_;
} }
void release() void release() const
{ {
if(--use_count_ == 0) delete this; if(--use_count_ == 0) delete this;
} }
@@ -103,12 +103,12 @@ long base::instances = 0;
namespace boost namespace boost
{ {
inline void intrusive_ptr_add_ref(N::base * p) inline void intrusive_ptr_add_ref(N::base const * p)
{ {
p->add_ref(); p->add_ref();
} }
inline void intrusive_ptr_release(N::base * p) inline void intrusive_ptr_release(N::base const * p)
{ {
p->release(); p->release();
} }
@@ -209,6 +209,58 @@ int main()
BOOST_TEST( N::base::instances == 0 ); BOOST_TEST( N::base::instances == 0 );
} }
{
boost::intrusive_ptr<X> px( new Y );
X * px2 = px.get();
boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>( std::move( px ) );
BOOST_TEST( py.get() == px2 );
BOOST_TEST( px.get() == 0 );
BOOST_TEST( py->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X const> px( new X );
X const * px2 = px.get();
boost::intrusive_ptr<X> px3 = boost::const_pointer_cast<X>( std::move( px ) );
BOOST_TEST( px3.get() == px2 );
BOOST_TEST( px.get() == 0 );
BOOST_TEST( px3->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new Y );
X * px2 = px.get();
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( std::move( px ) );
BOOST_TEST( py.get() == px2 );
BOOST_TEST( px.get() == 0 );
BOOST_TEST( py->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px( new X );
X * px2 = px.get();
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( std::move( px ) );
BOOST_TEST( py.get() == 0 );
BOOST_TEST( px.get() == px2 );
BOOST_TEST( px->use_count() == 1 );
}
BOOST_TEST( N::base::instances == 0 );
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -42,7 +42,7 @@ class base
{ {
private: private:
boost::detail::atomic_count use_count_; mutable boost::detail::atomic_count use_count_;
base(base const &); base(base const &);
base & operator=(base const &); base & operator=(base const &);
@@ -70,24 +70,24 @@ public:
#if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
inline friend void intrusive_ptr_add_ref(base * p) inline friend void intrusive_ptr_add_ref(base const * p)
{ {
++p->use_count_; ++p->use_count_;
} }
inline friend void intrusive_ptr_release(base * p) inline friend void intrusive_ptr_release(base const * p)
{ {
if(--p->use_count_ == 0) delete p; if(--p->use_count_ == 0) delete p;
} }
#else #else
void add_ref() void add_ref() const
{ {
++use_count_; ++use_count_;
} }
void release() void release() const
{ {
if(--use_count_ == 0) delete this; if(--use_count_ == 0) delete this;
} }
@@ -104,12 +104,12 @@ long base::instances = 0;
namespace boost namespace boost
{ {
inline void intrusive_ptr_add_ref(N::base * p) inline void intrusive_ptr_add_ref(N::base const * p)
{ {
p->add_ref(); p->add_ref();
} }
inline void intrusive_ptr_release(N::base * p) inline void intrusive_ptr_release(N::base const * p)
{ {
p->release(); p->release();
} }
@@ -303,14 +303,211 @@ namespace n_assignment
void copy_assignment() void copy_assignment()
{ {
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> p1;
p1 = p1;
BOOST_TEST(p1 == p1);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
boost::intrusive_ptr<X> p2;
p1 = p2;
BOOST_TEST(p1 == p2);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
boost::intrusive_ptr<X> p3(p1);
p1 = p3;
BOOST_TEST(p1 == p3);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
BOOST_TEST(N::base::instances == 0);
boost::intrusive_ptr<X> p4(new X);
BOOST_TEST(N::base::instances == 1);
p1 = p4;
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p1 == p4);
BOOST_TEST(p1->use_count() == 2);
p1 = p2;
BOOST_TEST(p1 == p2);
BOOST_TEST(N::base::instances == 1);
p4 = p3;
BOOST_TEST(p4 == p3);
BOOST_TEST(N::base::instances == 0);
}
} }
void conversion_assignment() void conversion_assignment()
{ {
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> p1;
boost::intrusive_ptr<Y> p2;
p1 = p2;
BOOST_TEST(p1 == p2);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
BOOST_TEST(N::base::instances == 0);
boost::intrusive_ptr<Y> p4(new Y);
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p4->use_count() == 1);
boost::intrusive_ptr<X> p5(p4);
BOOST_TEST(p4->use_count() == 2);
p1 = p4;
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p1 == p4);
BOOST_TEST(p1->use_count() == 3);
BOOST_TEST(p4->use_count() == 3);
p1 = p2;
BOOST_TEST(p1 == p2);
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p4->use_count() == 2);
p4 = p2;
p5 = p2;
BOOST_TEST(p4 == p2);
BOOST_TEST(N::base::instances == 0);
}
} }
void pointer_assignment() void pointer_assignment()
{ {
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> p1;
p1 = p1.get();
BOOST_TEST(p1 == p1);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
boost::intrusive_ptr<X> p2;
p1 = p2.get();
BOOST_TEST(p1 == p2);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
boost::intrusive_ptr<X> p3(p1);
p1 = p3.get();
BOOST_TEST(p1 == p3);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
BOOST_TEST(N::base::instances == 0);
boost::intrusive_ptr<X> p4(new X);
BOOST_TEST(N::base::instances == 1);
p1 = p4.get();
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p1 == p4);
BOOST_TEST(p1->use_count() == 2);
p1 = p2.get();
BOOST_TEST(p1 == p2);
BOOST_TEST(N::base::instances == 1);
p4 = p3.get();
BOOST_TEST(p4 == p3);
BOOST_TEST(N::base::instances == 0);
}
{
boost::intrusive_ptr<X> p1;
boost::intrusive_ptr<Y> p2;
p1 = p2.get();
BOOST_TEST(p1 == p2);
BOOST_TEST(p1? false: true);
BOOST_TEST(!p1);
BOOST_TEST(p1.get() == 0);
BOOST_TEST(N::base::instances == 0);
boost::intrusive_ptr<Y> p4(new Y);
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p4->use_count() == 1);
boost::intrusive_ptr<X> p5(p4);
BOOST_TEST(p4->use_count() == 2);
p1 = p4.get();
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p1 == p4);
BOOST_TEST(p1->use_count() == 3);
BOOST_TEST(p4->use_count() == 3);
p1 = p2.get();
BOOST_TEST(p1 == p2);
BOOST_TEST(N::base::instances == 1);
BOOST_TEST(p4->use_count() == 2);
p4 = p2.get();
p5 = p2.get();
BOOST_TEST(p4 == p2);
BOOST_TEST(N::base::instances == 0);
}
} }
void test() void test()
@@ -707,15 +904,137 @@ namespace n_static_cast
void test() void test()
{ {
{
boost::intrusive_ptr<X> px(new Y);
boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>(px);
BOOST_TEST(px.get() == py.get());
BOOST_TEST(px->use_count() == 2);
BOOST_TEST(py->use_count() == 2);
boost::intrusive_ptr<X> px2(py);
BOOST_TEST(px2.get() == px.get());
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>( boost::intrusive_ptr<X>(new Y) );
BOOST_TEST(py.get() != 0);
BOOST_TEST(py->use_count() == 1);
}
BOOST_TEST( N::base::instances == 0 );
} }
} // namespace n_static_cast } // namespace n_static_cast
namespace n_const_cast
{
void test()
{
{
boost::intrusive_ptr<X const> px;
boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>(px);
BOOST_TEST(px2.get() == 0);
}
{
boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>( boost::intrusive_ptr<X const>() );
BOOST_TEST(px2.get() == 0);
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X const> px(new X);
boost::intrusive_ptr<X> px2 = boost::const_pointer_cast<X>(px);
BOOST_TEST(px2.get() == px.get());
BOOST_TEST(px2->use_count() == 2);
BOOST_TEST(px->use_count() == 2);
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px = boost::const_pointer_cast<X>( boost::intrusive_ptr<X const>(new X) );
BOOST_TEST(px.get() != 0);
BOOST_TEST(px->use_count() == 1);
}
BOOST_TEST( N::base::instances == 0 );
}
} // namespace n_const_cast
namespace n_dynamic_cast namespace n_dynamic_cast
{ {
void test() void test()
{ {
{
boost::intrusive_ptr<X> px;
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == 0);
}
{
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>() );
BOOST_TEST(py.get() == 0);
}
{
boost::intrusive_ptr<X> px(static_cast<X*>(0));
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == 0);
}
{
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(static_cast<X*>(0)) );
BOOST_TEST(py.get() == 0);
}
{
boost::intrusive_ptr<X> px(new X);
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == 0);
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(new X) );
BOOST_TEST(py.get() == 0);
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px(new Y);
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>(px);
BOOST_TEST(py.get() == px.get());
BOOST_TEST(py->use_count() == 2);
BOOST_TEST(px->use_count() == 2);
}
BOOST_TEST( N::base::instances == 0 );
{
boost::intrusive_ptr<X> px(new Y);
boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( boost::intrusive_ptr<X>(new Y) );
BOOST_TEST(py.get() != 0);
BOOST_TEST(py->use_count() == 1);
}
BOOST_TEST( N::base::instances == 0 );
} }
} // namespace n_dynamic_cast } // namespace n_dynamic_cast
@@ -779,6 +1098,7 @@ int main()
n_swap::test(); n_swap::test();
n_comparison::test(); n_comparison::test();
n_static_cast::test(); n_static_cast::test();
n_const_cast::test();
n_dynamic_cast::test(); n_dynamic_cast::test();
n_transitive::test(); n_transitive::test();

View File

@@ -18,7 +18,7 @@ void f()
int main() int main()
{ {
int const N = 4; int const N = 4;
pthread_t th[ N ] = {}; boost::detail::lw_thread_t th[ N ] = {};
for( int i = 0; i < N; ++i ) for( int i = 0; i < N; ++i )
{ {
@@ -27,7 +27,7 @@ int main()
for( int i = 0; i < N; ++i ) for( int i = 0; i < N; ++i )
{ {
pthread_join( th[ i ], 0 ); boost::detail::lw_thread_join( th[ i ] );
} }
BOOST_TEST_EQ( count, N ); BOOST_TEST_EQ( count, N );

View File

@@ -0,0 +1,262 @@
// make_local_shared_const_test.cpp
//
// Copyright 2007-2009, 2017, 2018 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#if defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) || defined( BOOST_NO_CXX11_VARIADIC_TEMPLATES )
int main()
{
}
#else
#include <boost/core/lightweight_test.hpp>
#include <boost/smart_ptr/make_local_shared.hpp>
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <cstddef>
class X
{
private:
X( X const & );
X & operator=( X const & );
void * operator new( std::size_t n )
{
// lack of this definition causes link errors on Comeau C++
BOOST_ERROR( "private X::new called" );
return ::operator new( n );
}
void operator delete( void * p )
{
// lack of this definition causes link errors on MSVC
BOOST_ERROR( "private X::delete called" );
::operator delete( p );
}
public:
static int instances;
int v;
explicit X( int a1 = 0, int a2 = 0, int a3 = 0, int a4 = 0, int a5 = 0, int a6 = 0, int a7 = 0, int a8 = 0, int a9 = 0 ): v( a1+a2+a3+a4+a5+a6+a7+a8+a9 )
{
++instances;
}
~X()
{
--instances;
}
};
int X::instances = 0;
template<class T> static long use_count( boost::local_shared_ptr<T> const & p )
{
return boost::shared_ptr<T>( p ).use_count() - 1;
}
int main()
{
{
boost::local_shared_ptr<int const> pi = boost::make_local_shared<int const>();
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( *pi == 0 );
}
{
boost::local_shared_ptr<int const> pi = boost::make_local_shared<int const>( 5 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( *pi == 5 );
}
BOOST_TEST( X::instances == 0 );
{
boost::local_shared_ptr<X const> pi = boost::make_local_shared<X const>();
boost::weak_ptr<X const> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( pi->v == 0 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr<X const> pi = boost::make_local_shared_noinit<X const>();
boost::weak_ptr<X const> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( pi->v == 0 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr<X const> pi = boost::make_local_shared<X const>( 1 );
boost::weak_ptr<X const> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( pi->v == 1 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr<X const> pi = boost::make_local_shared<X const>( 1, 2 );
boost::weak_ptr<X const> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( pi->v == 1+2 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr<X const> pi = boost::make_local_shared<X const>( 1, 2, 3 );
boost::weak_ptr<X const> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( pi->v == 1+2+3 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr<X const> pi = boost::make_local_shared<X const>( 1, 2, 3, 4 );
boost::weak_ptr<X const> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( pi->v == 1+2+3+4 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr<X const> pi = boost::make_local_shared<X const>( 1, 2, 3, 4, 5 );
boost::weak_ptr<X const> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( pi->v == 1+2+3+4+5 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr<X const> pi = boost::make_local_shared<X const>( 1, 2, 3, 4, 5, 6 );
boost::weak_ptr<X const> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( pi->v == 1+2+3+4+5+6 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr<X const> pi = boost::make_local_shared<X const>( 1, 2, 3, 4, 5, 6, 7 );
boost::weak_ptr<X const> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr<X const> pi = boost::make_local_shared<X const>( 1, 2, 3, 4, 5, 6, 7, 8 );
boost::weak_ptr<X const> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
{
boost::local_shared_ptr<X const> pi = boost::make_local_shared<X const>( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
boost::weak_ptr<X const> wp( pi );
BOOST_TEST( X::instances == 1 );
BOOST_TEST( pi.get() != 0 );
BOOST_TEST( pi.local_use_count() == 1 );
BOOST_TEST( use_count( pi ) == 1 );
BOOST_TEST( pi->v == 1+2+3+4+5+6+7+8+9 );
pi.reset();
BOOST_TEST( X::instances == 0 );
}
return boost::report_errors();
}
#endif

View File

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

View File

@@ -764,7 +764,7 @@ void weak_ptr_constructor()
boost::shared_ptr<Y> p2(wp); boost::shared_ptr<Y> p2(wp);
BOOST_ERROR("shared_ptr<Y> p2(wp) failed to throw"); BOOST_ERROR("shared_ptr<Y> p2(wp) failed to throw");
} }
catch(boost::bad_weak_ptr) catch(boost::bad_weak_ptr const&)
{ {
} }
@@ -773,7 +773,7 @@ void weak_ptr_constructor()
boost::shared_ptr<X> p3(wp); boost::shared_ptr<X> p3(wp);
BOOST_ERROR("shared_ptr<X> p3(wp) failed to throw"); BOOST_ERROR("shared_ptr<X> p3(wp) failed to throw");
} }
catch(boost::bad_weak_ptr) catch(boost::bad_weak_ptr const&)
{ {
} }
} }
@@ -829,7 +829,7 @@ void weak_ptr_constructor()
boost::shared_ptr<Y> p2(wp); boost::shared_ptr<Y> p2(wp);
BOOST_ERROR("shared_ptr<Y> p2(wp) failed to throw"); BOOST_ERROR("shared_ptr<Y> p2(wp) failed to throw");
} }
catch(boost::bad_weak_ptr) catch(boost::bad_weak_ptr const&)
{ {
} }
@@ -838,7 +838,7 @@ void weak_ptr_constructor()
boost::shared_ptr<X> p3(wp); boost::shared_ptr<X> p3(wp);
BOOST_ERROR("shared_ptr<X> p3(wp) failed to throw"); BOOST_ERROR("shared_ptr<X> p3(wp) failed to throw");
} }
catch(boost::bad_weak_ptr) catch(boost::bad_weak_ptr const&)
{ {
} }
} }

View File

@@ -17,7 +17,7 @@
# undef HAVE_CONSTEXPR_INIT # undef HAVE_CONSTEXPR_INIT
#endif #endif
#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 ) #if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
# undef HAVE_CONSTEXPR_INIT # undef HAVE_CONSTEXPR_INIT
#endif #endif

View File

@@ -17,7 +17,7 @@
# undef HAVE_CONSTEXPR_INIT # undef HAVE_CONSTEXPR_INIT
#endif #endif
#if BOOST_WORKAROUND( BOOST_MSVC, < 1920 ) #if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
# undef HAVE_CONSTEXPR_INIT # undef HAVE_CONSTEXPR_INIT
#endif #endif

View File

@@ -13,9 +13,20 @@
#include <boost/smart_ptr/detail/sp_interlocked.hpp> #include <boost/smart_ptr/detail/sp_interlocked.hpp>
#include <boost/detail/lightweight_test.hpp> #include <boost/detail/lightweight_test.hpp>
#ifndef __LP64__
typedef long long_type;
#else
// On Cygwin 64, long is 64 bit
typedef int long_type;
#endif
int main() int main()
{ {
long x = 0, r; long_type x = 0, r;
r = BOOST_SP_INTERLOCKED_INCREMENT( &x ); r = BOOST_SP_INTERLOCKED_INCREMENT( &x );

View File

@@ -0,0 +1,11 @@
// Copyright 2018 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# include <windows.h>
# include <boost/shared_ptr.hpp>
#endif
int main()
{
}

View File

@@ -0,0 +1,11 @@
// Copyright 2018 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# include <windows.h>
# include <boost/smart_ptr/detail/spinlock.hpp>
#endif
int main()
{
}

View File

@@ -0,0 +1,97 @@
// weak_ptr_alias_move_test.cpp
//
// Copyright 2007, 2019 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/core/lightweight_test.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/config.hpp>
#include <memory>
#include <cstddef>
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
class incomplete;
struct X
{
int v_;
explicit X( int v ): v_( v )
{
}
~X()
{
v_ = 0;
}
};
template<class P1, class P2> bool share_ownership( P1 const& p1, P2 const& p2 )
{
return !p1.owner_before( p2 ) && !p2.owner_before( p1 );
}
int main()
{
{
boost::shared_ptr<float> p( new float );
boost::weak_ptr<float> p2( p );
int m2 = 0;
boost::weak_ptr<int const volatile> p3( std::move( p2 ), &m2 );
BOOST_TEST( p3.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p3 ) );
BOOST_TEST( p3.lock().get() == &m2 );
BOOST_TEST( p2.empty() );
}
{
boost::shared_ptr<incomplete> p;
boost::weak_ptr<incomplete> p2( p );
int m2 = 0;
boost::weak_ptr<int const volatile> p3( std::move( p2 ), &m2 );
BOOST_TEST( p3.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p3 ) );
BOOST_TEST( p3.lock().get() == 0 );
BOOST_TEST( p2.empty() );
}
{
boost::shared_ptr<X> p( new X( 5 ) );
boost::weak_ptr<X> p2( p );
boost::weak_ptr<int const volatile> p3( std::move( p2 ), &p2.lock()->v_ );
BOOST_TEST( p3.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p3 ) );
BOOST_TEST( p3.lock().get() == &p->v_ );
BOOST_TEST( p2.empty() );
p.reset();
BOOST_TEST( p3.expired() );
}
return boost::report_errors();
}
#else // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
int main()
{
return 0;
}
#endif

View File

@@ -0,0 +1,203 @@
// weak_ptr_alias_test.cpp
//
// Copyright 2007, 2019 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/core/lightweight_test.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <memory>
#include <cstddef>
//
class incomplete;
struct X
{
int v_;
explicit X( int v ): v_( v )
{
}
~X()
{
v_ = 0;
}
};
template<class P1, class P2> bool share_ownership( P1 const& p1, P2 const& p2 )
{
return !p1.owner_before( p2 ) && !p2.owner_before( p1 );
}
int main()
{
{
boost::shared_ptr<double> p( new double );
float m = 0;
boost::weak_ptr<float> p2( p, &m );
BOOST_TEST( p2.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p2 ) );
BOOST_TEST( p2.lock().get() == &m );
{
int m2 = 0;
boost::weak_ptr<int> p3( p2, &m2 );
BOOST_TEST( p3.use_count() == p2.use_count() );
BOOST_TEST( share_ownership( p2, p3 ) );
BOOST_TEST( p3.lock().get() == &m2 );
}
{
int m2 = 0;
boost::weak_ptr<int const> p3( p, &m2 );
BOOST_TEST( p3.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p3 ) );
BOOST_TEST( p3.lock().get() == &m2 );
}
{
int m2 = 0;
boost::weak_ptr<int volatile> p3( p2, &m2 );
BOOST_TEST( p3.use_count() == p2.use_count() );
BOOST_TEST( share_ownership( p2, p3 ) );
BOOST_TEST( p3.lock().get() == &m2 );
}
{
int m2 = 0;
boost::weak_ptr<void> p3( p, &m2 );
BOOST_TEST( p3.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p3 ) );
BOOST_TEST( p3.lock().get() == &m2 );
}
{
int m2 = 0;
boost::weak_ptr<void> p3( p2, &m2 );
BOOST_TEST( p3.use_count() == p2.use_count() );
BOOST_TEST( share_ownership( p2, p3 ) );
BOOST_TEST( p3.lock().get() == &m2 );
}
{
int m2 = 0;
boost::weak_ptr<void const volatile> p3( p, &m2 );
BOOST_TEST( p3.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p3 ) );
BOOST_TEST( p3.lock().get() == &m2 );
}
{
int m2 = 0;
boost::weak_ptr<void const volatile> p3( p2, &m2 );
BOOST_TEST( p3.use_count() == p2.use_count() );
BOOST_TEST( share_ownership( p2, p3 ) );
BOOST_TEST( p3.lock().get() == &m2 );
}
}
{
boost::shared_ptr<incomplete> p;
float m = 0;
boost::weak_ptr<float> p2( p, &m );
BOOST_TEST( p2.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p2 ) );
{
int m2 = 0;
boost::weak_ptr<int> p3( p2, &m2 );
BOOST_TEST( p3.use_count() == p2.use_count() );
BOOST_TEST( share_ownership( p2, p3 ) );
BOOST_TEST( p3.lock().get() == 0 );
}
{
int m2 = 0;
boost::weak_ptr<int const> p3( p, &m2 );
BOOST_TEST( p3.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p3 ) );
BOOST_TEST( p3.lock().get() == 0 );
}
{
int m2 = 0;
boost::weak_ptr<int volatile> p3( p2, &m2 );
BOOST_TEST( p3.use_count() == p2.use_count() );
BOOST_TEST( share_ownership( p2, p3 ) );
BOOST_TEST( p3.lock().get() == 0 );
}
{
int m2 = 0;
boost::weak_ptr<void> p3( p, &m2 );
BOOST_TEST( p3.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p3 ) );
BOOST_TEST( p3.lock().get() == 0 );
}
{
int m2 = 0;
boost::weak_ptr<void> p3( p2, &m2 );
BOOST_TEST( p3.use_count() == p2.use_count() );
BOOST_TEST( share_ownership( p2, p3 ) );
BOOST_TEST( p3.lock().get() == 0 );
}
{
int m2 = 0;
boost::weak_ptr<void const volatile> p3( p, &m2 );
BOOST_TEST( p3.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p3 ) );
BOOST_TEST( p3.lock().get() == 0 );
}
{
int m2 = 0;
boost::weak_ptr<void const volatile> p3( p2, &m2 );
BOOST_TEST( p3.use_count() == p2.use_count() );
BOOST_TEST( share_ownership( p2, p3 ) );
BOOST_TEST( p3.lock().get() == 0 );
}
}
{
boost::shared_ptr<X> p( new X( 5 ) );
boost::weak_ptr<int const> p2( p, &p->v_ );
BOOST_TEST( p2.use_count() == p.use_count() );
BOOST_TEST( share_ownership( p, p2 ) );
BOOST_TEST( p2.lock().get() == &p->v_ );
p.reset();
BOOST_TEST( p2.expired() );
}
return boost::report_errors();
}

View File

@@ -0,0 +1,11 @@
// Copyright 2018 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# include <windows.h>
# include <boost/smart_ptr/detail/yield_k.hpp>
#endif
int main()
{
}