diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-09-13 11:24:46 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-09-13 11:25:39 +0900 |
commit | 4fadd968fa12130524c8380f33fcfe25d4de79e5 (patch) | |
tree | fd26a490cd15388d42fc6652b3c5c13012e7f93e /boost/smart_ptr | |
parent | b5c87084afaef42b2d058f68091be31988a6a874 (diff) | |
download | boost-upstream/1.65.0.tar.gz boost-upstream/1.65.0.tar.bz2 boost-upstream/1.65.0.zip |
Imported Upstream version 1.65.0upstream/1.65.0
Change-Id: Icf8400b375482cb11bcf77440a6934ba360d6ba4
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'boost/smart_ptr')
47 files changed, 2331 insertions, 916 deletions
diff --git a/boost/smart_ptr/allocate_local_shared_array.hpp b/boost/smart_ptr/allocate_local_shared_array.hpp new file mode 100644 index 0000000000..f46f11049b --- /dev/null +++ b/boost/smart_ptr/allocate_local_shared_array.hpp @@ -0,0 +1,228 @@ +/* +Copyright 2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP +#define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP + +#include <boost/smart_ptr/allocate_shared_array.hpp> +#include <boost/smart_ptr/local_shared_ptr.hpp> + +namespace boost { +namespace detail { + +template<class> +struct lsp_if_array { }; + +template<class T> +struct lsp_if_array<T[]> { + typedef boost::local_shared_ptr<T[]> type; +}; + +template<class> +struct lsp_if_size_array { }; + +template<class T, std::size_t N> +struct lsp_if_size_array<T[N]> { + typedef boost::local_shared_ptr<T[N]> type; +}; + +class lsp_array_base + : public local_counted_base { +public: + void set(sp_counted_base* base) BOOST_SP_NOEXCEPT { + count_ = shared_count(base); + } + + virtual void local_cb_destroy() BOOST_SP_NOEXCEPT { + shared_count().swap(count_); + } + + virtual shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT { + return count_; + } + +private: + shared_count count_; +}; + +template<class A> +class lsp_array_state + : public sp_array_state<A> { +public: + template<class U> + lsp_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT + : sp_array_state<A>(other, size) { } + + lsp_array_base& base() BOOST_SP_NOEXCEPT { + return base_; + } + +private: + lsp_array_base base_; +}; + +template<class A, std::size_t N> +class lsp_size_array_state + : public sp_size_array_state<A, N> { +public: + template<class U> + lsp_size_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT + : sp_size_array_state<A, N>(other, size) { } + + lsp_array_base& base() BOOST_SP_NOEXCEPT { + return base_; + } + +private: + lsp_array_base base_; +}; + +} /* detail */ + +template<class T, class A> +inline typename detail::lsp_if_array<T>::type +allocate_local_shared(const A& allocator, std::size_t count) +{ + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::lsp_array_state<other> state; + typedef detail::sp_array_base<state> base; + std::size_t size = count * detail::sp_array_count<type>::value; + detail::sp_array_result<other, base> result(allocator, size); + base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, start); + detail::lsp_array_base& local = node->state().base(); + local.set(node); + result.release(); + return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), + reinterpret_cast<type*>(start), &local); +} + +template<class T, class A> +inline typename detail::lsp_if_size_array<T>::type +allocate_local_shared(const A& allocator) +{ + enum { + size = detail::sp_array_count<T>::value + }; + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::lsp_size_array_state<other, size> state; + typedef detail::sp_array_base<state> base; + detail::sp_array_result<other, base> result(allocator, size); + base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, start); + detail::lsp_array_base& local = node->state().base(); + local.set(node); + result.release(); + return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), + reinterpret_cast<type*>(start), &local); +} + +template<class T, class A> +inline typename detail::lsp_if_array<T>::type +allocate_local_shared(const A& allocator, std::size_t count, + const typename detail::sp_array_element<T>::type& value) +{ + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::lsp_array_state<other> state; + typedef detail::sp_array_base<state> base; + std::size_t size = count * detail::sp_array_count<type>::value; + detail::sp_array_result<other, base> result(allocator, size); + base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, + reinterpret_cast<const scalar*>(&value), + detail::sp_array_count<type>::value, start); + detail::lsp_array_base& local = node->state().base(); + local.set(node); + result.release(); + return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), + reinterpret_cast<type*>(start), &local); +} + +template<class T, class A> +inline typename detail::lsp_if_size_array<T>::type +allocate_local_shared(const A& allocator, + const typename detail::sp_array_element<T>::type& value) +{ + enum { + size = detail::sp_array_count<T>::value + }; + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::lsp_size_array_state<other, size> state; + typedef detail::sp_array_base<state> base; + detail::sp_array_result<other, base> result(allocator, size); + base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, + reinterpret_cast<const scalar*>(&value), + detail::sp_array_count<type>::value, start); + detail::lsp_array_base& local = node->state().base(); + local.set(node); + result.release(); + return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), + reinterpret_cast<type*>(start), &local); +} + +template<class T, class A> +inline typename detail::lsp_if_array<T>::type +allocate_local_shared_noinit(const A& allocator, std::size_t count) +{ + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::lsp_array_state<other> state; + typedef detail::sp_array_base<state, false> base; + std::size_t size = count * detail::sp_array_count<type>::value; + detail::sp_array_result<other, base> result(allocator, size); + base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator, + size, start); + detail::lsp_array_base& local = node->state().base(); + local.set(node); + result.release(); + return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), + reinterpret_cast<type*>(start), &local); +} + +template<class T, class A> +inline typename detail::lsp_if_size_array<T>::type +allocate_local_shared_noinit(const A& allocator) +{ + enum { + size = detail::sp_array_count<T>::value + }; + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::lsp_size_array_state<other, size> state; + typedef detail::sp_array_base<state, false> base; + detail::sp_array_result<other, base> result(allocator, size); + base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator, + size, start); + detail::lsp_array_base& local = node->state().base(); + local.set(node); + result.release(); + return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), + reinterpret_cast<type*>(start), &local); +} + +} /* boost */ + +#endif diff --git a/boost/smart_ptr/allocate_shared_array.hpp b/boost/smart_ptr/allocate_shared_array.hpp index b43b43d575..23c35aff3f 100644 --- a/boost/smart_ptr/allocate_shared_array.hpp +++ b/boost/smart_ptr/allocate_shared_array.hpp @@ -9,9 +9,10 @@ Distributed under the Boost Software License, Version 1.0. #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP #include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/type_traits/alignment_of.hpp> +#include <boost/type_traits/has_trivial_assign.hpp> #include <boost/type_traits/has_trivial_constructor.hpp> #include <boost/type_traits/has_trivial_destructor.hpp> -#include <boost/type_traits/alignment_of.hpp> #include <boost/type_traits/type_with_alignment.hpp> namespace boost { @@ -105,37 +106,24 @@ struct sp_array_count<T[N]> { }; }; -template<class T> -struct sp_array_count<T[]> { }; - -template<class D, class T> -inline D* -sp_get_deleter(const - boost::shared_ptr<T>& value) BOOST_NOEXCEPT_OR_NOTHROW -{ - return static_cast<D*>(value._internal_get_untyped_deleter()); -} - -template<std::size_t N, std::size_t A> -struct sp_array_storage { - union type { - char value[N]; - typename boost::type_with_alignment<A>::type other; +template<std::size_t N, std::size_t M> +struct sp_max_size { + enum { + value = N < M ? M : N }; }; template<std::size_t N, std::size_t M> -struct sp_max_size { +struct sp_align_up { enum { - value = N < M ? M : N + value = (N + M - 1) & ~(M - 1) }; }; #if !defined(BOOST_NO_CXX11_ALLOCATOR) template<class A, class T> struct sp_bind_allocator { - typedef typename std::allocator_traits<A>::template - rebind_alloc<T> type; + typedef typename std::allocator_traits<A>::template rebind_alloc<T> type; }; #else template<class A, class T> @@ -144,6 +132,13 @@ struct sp_bind_allocator { }; #endif +template<class T> +BOOST_CONSTEXPR inline std::size_t +sp_objects(std::size_t size) BOOST_SP_NOEXCEPT +{ + return (size + sizeof(T) - 1) / sizeof(T); +} + template<bool, class = void> struct sp_enable { }; @@ -152,873 +147,549 @@ struct sp_enable<true, T> { typedef T type; }; -template<class T> -inline -typename sp_enable<boost::has_trivial_destructor<T>::value>::type -sp_array_destroy(T*, std::size_t) BOOST_NOEXCEPT { } +template<bool E, class A, class T> +inline typename sp_enable<!E && boost::has_trivial_destructor<T>::value>::type +sp_array_destroy(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { } -template<class T> -inline -typename sp_enable<!boost::has_trivial_destructor<T>::value>::type -sp_array_destroy(T* storage, std::size_t size) +template<bool E, class A, class T> +inline typename sp_enable<!E && + !boost::has_trivial_destructor<T>::value>::type +sp_array_destroy(A&, T* start, std::size_t size) { while (size > 0) { - storage[--size].~T(); + start[--size].~T(); } } #if !defined(BOOST_NO_CXX11_ALLOCATOR) -template<class A, class T> -inline void -sp_array_destroy(A& allocator, T* storage, std::size_t size) +template<bool E, class A, class T> +inline typename sp_enable<E>::type +sp_array_destroy(A& allocator, T* start, std::size_t size) { while (size > 0) { - std::allocator_traits<A>::destroy(allocator, &storage[--size]); + std::allocator_traits<A>::destroy(allocator, start + --size); } } #endif -#if !defined(BOOST_NO_EXCEPTIONS) -template<class T> -inline -typename sp_enable<boost::has_trivial_constructor<T>::value || - boost::has_trivial_destructor<T>::value>::type -sp_array_construct(T* storage, std::size_t size) +template<bool E, class A, class T> +inline typename sp_enable<!E && + boost::has_trivial_constructor<T>::value && + boost::has_trivial_assign<T>::value>::type +sp_array_construct(A&, T* start, std::size_t size) { for (std::size_t i = 0; i < size; ++i) { - ::new(static_cast<void*>(storage + i)) T(); + start[i] = T(); } } -template<class T> -inline -typename sp_enable<!boost::has_trivial_constructor<T>::value && - !boost::has_trivial_destructor<T>::value>::type -sp_array_construct(T* storage, std::size_t size) +template<bool E, class A, class T> +inline typename sp_enable<!E && + boost::has_trivial_constructor<T>::value && + boost::has_trivial_assign<T>::value>::type +sp_array_construct(A&, T* start, std::size_t size, const T* list, + std::size_t count) +{ + for (std::size_t i = 0; i < size; ++i) { + start[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)>::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*>(storage + i)) T(); + ::new(static_cast<void*>(start + i)) T(); } } catch (...) { - while (i > 0) { - storage[--i].~T(); - } + sp_array_destroy<E>(none, start, i); throw; } } -template<class T> -inline void -sp_array_construct(T* storage, std::size_t size, const T* list, +template<bool E, class A, class T> +inline typename sp_enable<!E && + !(boost::has_trivial_constructor<T>::value && + boost::has_trivial_assign<T>::value)>::type +sp_array_construct(A& none, T* start, std::size_t size, const T* list, std::size_t count) { std::size_t i = 0; try { for (; i < size; ++i) { - ::new(static_cast<void*>(storage + i)) T(list[i % count]); + ::new(static_cast<void*>(start + i)) T(list[i % count]); } } catch (...) { - while (i > 0) { - storage[--i].~T(); - } + sp_array_destroy<E>(none, start, i); throw; } } #else -template<class T> -inline void -sp_array_construct(T* storage, std::size_t size) +template<bool E, class A, class T> +inline typename sp_enable<!E && + !(boost::has_trivial_constructor<T>::value && + boost::has_trivial_assign<T>::value)>::type +sp_array_construct(A&, T* start, std::size_t size) { for (std::size_t i = 0; i < size; ++i) { - ::new(static_cast<void*>(storage + i)) T(); + ::new(static_cast<void*>(start + i)) T(); } } -template<class T> -inline void -sp_array_construct(T* storage, std::size_t size, const T* list, +template<bool E, class A, class T> +inline typename sp_enable<!E && + !(boost::has_trivial_constructor<T>::value && + boost::has_trivial_assign<T>::value)>::type +sp_array_construct(A&, T* start, std::size_t size, const T* list, std::size_t count) { for (std::size_t i = 0; i < size; ++i) { - ::new(static_cast<void*>(storage + i)) T(list[i % count]); + ::new(static_cast<void*>(start + i)) T(list[i % count]); } } #endif #if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_EXCEPTIONS) -template<class A, class T> -inline void -sp_array_construct(A& allocator, T* storage, std::size_t size) +template<bool E, class A, class T> +inline typename sp_enable<E>::type +sp_array_construct(A& allocator, T* start, std::size_t size) { std::size_t i = 0; try { for (i = 0; i < size; ++i) { - std::allocator_traits<A>::construct(allocator, storage + i); + std::allocator_traits<A>::construct(allocator, start + i); } } catch (...) { - sp_array_destroy(allocator, storage, i); + sp_array_destroy<E>(allocator, start, i); throw; } } -template<class A, class T> -inline void -sp_array_construct(A& allocator, T* storage, std::size_t size, - const T* list, std::size_t count) +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) { std::size_t i = 0; try { for (i = 0; i < size; ++i) { - std::allocator_traits<A>::construct(allocator, storage + i, + std::allocator_traits<A>::construct(allocator, start + i, list[i % count]); } } catch (...) { - sp_array_destroy(allocator, storage, i); + sp_array_destroy<E>(allocator, start, i); throw; } } #else -template<class A, class T> -inline void -sp_array_construct(A& allocator, T* storage, std::size_t size) +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, storage + i); + std::allocator_traits<A>::construct(allocator, start + i); } } -template<class A, class T> -inline void -sp_array_construct(A& allocator, T* storage, std::size_t size, - const T* list, std::size_t count) +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, storage + i, + std::allocator_traits<A>::construct(allocator, start + i, list[i % count]); } } #endif #endif -template<class T> -inline -typename sp_enable<boost::has_trivial_constructor<T>::value>::type -sp_array_default(T*, std::size_t) BOOST_NOEXCEPT { } +template<class A, class T> +inline typename sp_enable<boost::has_trivial_constructor<T>::value>::type +sp_array_default(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { } #if !defined(BOOST_NO_EXCEPTIONS) -template<class T> -inline -typename sp_enable<!boost::has_trivial_constructor<T>::value && - boost::has_trivial_destructor<T>::value>::type -sp_array_default(T* storage, std::size_t size) -{ - for (std::size_t i = 0; i < size; ++i) { - ::new(static_cast<void*>(storage + i)) T; - } -} - -template<class T> -inline -typename sp_enable<!boost::has_trivial_constructor<T>::value && - !boost::has_trivial_destructor<T>::value>::type -sp_array_default(T* storage, std::size_t size) +template<class A, class T> +inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type +sp_array_default(A& none, T* start, std::size_t size) { std::size_t i = 0; try { for (; i < size; ++i) { - ::new(static_cast<void*>(storage + i)) T; + ::new(static_cast<void*>(start + i)) T; } } catch (...) { - while (i > 0) { - storage[--i].~T(); - } + sp_array_destroy<false>(none, start, i); throw; } } #else -template<class T> -inline -typename sp_enable<!boost::has_trivial_constructor<T>::value>::type -sp_array_default(T* storage, std::size_t size) +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*>(storage + i)) T; + ::new(static_cast<void*>(start + i)) T; } } #endif -template<class T, std::size_t N> -struct sp_less_align { - enum { - value = (boost::alignment_of<T>::value) < N - }; -}; - -template<class T, std::size_t N> -BOOST_CONSTEXPR inline -typename sp_enable<sp_less_align<T, N>::value, std::size_t>::type -sp_align(std::size_t size) BOOST_NOEXCEPT -{ - return (sizeof(T) * size + N - 1) & ~(N - 1); -} - -template<class T, std::size_t N> -BOOST_CONSTEXPR inline -typename sp_enable<!sp_less_align<T, N>::value, std::size_t>::type -sp_align(std::size_t size) BOOST_NOEXCEPT -{ - return sizeof(T) * size; -} - -template<class T> -BOOST_CONSTEXPR inline std::size_t -sp_types(std::size_t size) BOOST_NOEXCEPT -{ - return (size + sizeof(T) - 1) / sizeof(T); -} - -template<class T, std::size_t N> -class sp_size_array_deleter { -public: - template<class U> - static void operator_fn(U) BOOST_NOEXCEPT { } - - sp_size_array_deleter() BOOST_NOEXCEPT - : enabled_(false) { } - - template<class A> - sp_size_array_deleter(const A&) BOOST_NOEXCEPT - : enabled_(false) { } - - sp_size_array_deleter(const sp_size_array_deleter&) BOOST_NOEXCEPT - : enabled_(false) { } - - ~sp_size_array_deleter() { - if (enabled_) { - sp_array_destroy(reinterpret_cast<T*>(&storage_), N); - } - } - - template<class U> - void operator()(U) { - if (enabled_) { - sp_array_destroy(reinterpret_cast<T*>(&storage_), N); - enabled_ = false; - } - } - - void* construct() { - sp_array_construct(reinterpret_cast<T*>(&storage_), N); - enabled_ = true; - return &storage_; - } - - void* construct(const T* list, std::size_t count) { - sp_array_construct(reinterpret_cast<T*>(&storage_), N, - list, count); - enabled_ = true; - return &storage_; - } - - void* construct_default() { - sp_array_default(reinterpret_cast<T*>(&storage_), N); - enabled_ = true; - return &storage_; - } - -private: - bool enabled_; - typename sp_array_storage<sizeof(T) * N, - boost::alignment_of<T>::value>::type storage_; -}; - -#if !defined(BOOST_NO_CXX11_ALLOCATOR) -template<class T, std::size_t N, class A> -class sp_size_array_destroyer { +template<class A> +class sp_array_state { public: - template<class U> - static void operator_fn(U) BOOST_NOEXCEPT { } + typedef A type; template<class U> - sp_size_array_destroyer(const U& allocator) BOOST_NOEXCEPT + sp_array_state(const U& allocator, std::size_t size) BOOST_SP_NOEXCEPT : allocator_(allocator), - enabled_(false) { } - - sp_size_array_destroyer(const sp_size_array_destroyer& other) - BOOST_NOEXCEPT - : allocator_(other.allocator_), - enabled_(false) { } - - ~sp_size_array_destroyer() { - if (enabled_) { - sp_array_destroy(allocator_, - reinterpret_cast<T*>(&storage_), N); - } - } - - template<class U> - void operator()(U) { - if (enabled_) { - sp_array_destroy(allocator_, - reinterpret_cast<T*>(&storage_), N); - enabled_ = false; - } - } - - void* construct() { - sp_array_construct(allocator_, - reinterpret_cast<T*>(&storage_), N); - enabled_ = true; - return &storage_; - } - - void* construct(const T* list, std::size_t count) { - sp_array_construct(allocator_, - reinterpret_cast<T*>(&storage_), N, list, count); - enabled_ = true; - return &storage_; - } - - const A& allocator() const BOOST_NOEXCEPT { - return allocator_; - } - -private: - typename sp_array_storage<sizeof(T) * N, - boost::alignment_of<T>::value>::type storage_; - A allocator_; - bool enabled_; -}; -#endif - -template<class T> -class sp_array_deleter { -public: - template<class U> - static void operator_fn(U) BOOST_NOEXCEPT { } - - sp_array_deleter(std::size_t size) BOOST_NOEXCEPT - : address_(0), size_(size) { } - template<class A> - sp_array_deleter(const A& allocator) BOOST_NOEXCEPT - : address_(0), - size_(allocator.size()) { } - - template<class A> - sp_array_deleter(const A&, std::size_t size) BOOST_NOEXCEPT - : address_(0), - size_(size) { } - - sp_array_deleter(const sp_array_deleter& other) BOOST_NOEXCEPT - : address_(0), - size_(other.size_) { } - - ~sp_array_deleter() { - if (address_) { - sp_array_destroy(static_cast<T*>(address_), size_); - } - } - - template<class U> - void operator()(U) { - if (address_) { - sp_array_destroy(static_cast<T*>(address_), size_); - address_ = 0; - } - } - - void construct(T* address) { - sp_array_construct(address, size_); - address_ = address; - } - - void construct(T* address, const T* list, std::size_t count) { - sp_array_construct(address, size_, list, count); - address_ = address; - } - - void construct_default(T* address) { - sp_array_default(address, size_); - address_ = address; - } - - std::size_t size() const BOOST_NOEXCEPT { - return size_; - } - -private: - void* address_; - std::size_t size_; -}; - -#if !defined(BOOST_NO_CXX11_ALLOCATOR) -template<class T, class A> -class sp_array_destroyer { -public: - template<class U> - static void operator_fn(U) BOOST_NOEXCEPT { } - - template<class U> - sp_array_destroyer(const U& allocator, std::size_t size) - BOOST_NOEXCEPT - : allocator_(allocator), - size_(size), - address_(0) { } - - template<class U> - sp_array_destroyer(const U& allocator) BOOST_NOEXCEPT - : allocator_(allocator.allocator()), - size_(allocator.size()), - address_(0) { } - - sp_array_destroyer(const sp_array_destroyer& other) BOOST_NOEXCEPT - : allocator_(other.allocator_), - size_(other.size_), - address_(0) { } - - ~sp_array_destroyer() { - if (address_) { - sp_array_destroy(allocator_, static_cast<T*>(address_), - size_); - } - } - - template<class U> - void operator()(U) { - if (address_) { - sp_array_destroy(allocator_, static_cast<T*>(address_), - size_); - address_ = 0; - } - } - - void construct(T* address) { - sp_array_construct(allocator_, address, size_); - address_ = address; - } - - void construct(T* address, const T* list, std::size_t count) { - sp_array_construct(allocator_, address, size_, list, count); - address_ = address; - } - - const A& allocator() const BOOST_NOEXCEPT { + A& allocator() BOOST_SP_NOEXCEPT { return allocator_; } - std::size_t size() const BOOST_NOEXCEPT { + std::size_t size() const BOOST_SP_NOEXCEPT { return size_; } private: A allocator_; std::size_t size_; - void* address_; }; -#endif - -template<class T, class A> -class sp_array_allocator { - template<class U, class V> - friend class sp_array_allocator; +template<class A, std::size_t N> +class sp_size_array_state { public: - typedef typename A::value_type value_type; - -private: - enum { - alignment = sp_max_size<boost::alignment_of<T>::value, - boost::alignment_of<value_type>::value>::value - }; - - typedef typename boost::type_with_alignment<alignment>::type type; - typedef typename sp_bind_allocator<A, type>::type type_allocator; - -public: - template<class U> - struct rebind { - typedef sp_array_allocator<T, - typename sp_bind_allocator<A, U>::type> other; - }; - - sp_array_allocator(const A& allocator, std::size_t size, - void** result) BOOST_NOEXCEPT - : allocator_(allocator), - size_(size), - result_(result) { } - - sp_array_allocator(const A& allocator, std::size_t size) - BOOST_NOEXCEPT - : allocator_(allocator), - size_(size) { } + typedef A type; template<class U> - sp_array_allocator(const sp_array_allocator<T, U>& other) - BOOST_NOEXCEPT - : allocator_(other.allocator_), - size_(other.size_), - result_(other.result_) { } - - value_type* allocate(std::size_t count) { - type_allocator allocator(allocator_); - std::size_t node = sp_align<value_type, alignment>(count); - std::size_t size = sp_types<type>(node + sizeof(T) * size_); - type* address = allocator.allocate(size); - *result_ = reinterpret_cast<char*>(address) + node; - return reinterpret_cast<value_type*>(address); - } + sp_size_array_state(const U& allocator, std::size_t) BOOST_SP_NOEXCEPT + : allocator_(allocator) { } - void deallocate(value_type* value, std::size_t count) { - type_allocator allocator(allocator_); - std::size_t node = sp_align<value_type, alignment>(count); - std::size_t size = sp_types<type>(node + sizeof(T) * size_); - allocator.deallocate(reinterpret_cast<type*>(value), size); - } - - const A& allocator() const BOOST_NOEXCEPT { + A& allocator() BOOST_SP_NOEXCEPT { return allocator_; } - std::size_t size() const BOOST_NOEXCEPT { - return size_; + BOOST_CONSTEXPR std::size_t size() const BOOST_SP_NOEXCEPT { + return N; } private: A allocator_; - std::size_t size_; - void** result_; }; -template<class T, class U, class V> -inline bool -operator==(const sp_array_allocator<T, U>& first, - const sp_array_allocator<T, V>& second) BOOST_NOEXCEPT -{ - return first.allocator() == second.allocator() && - first.size() == second.size(); -} - -template<class T, class U, class V> -inline bool -operator!=(const sp_array_allocator<T, U>& first, - const sp_array_allocator<T, V>& second) BOOST_NOEXCEPT -{ - return !(first == second); -} - #if !defined(BOOST_NO_CXX11_ALLOCATOR) -template<class A, class T, std::size_t N> -struct sp_select_size_deleter { - typedef sp_size_array_destroyer<T, N, - typename sp_bind_allocator<A, T>::type> type; +template<class A> +struct sp_use_construct { + enum { + value = true + }; }; -template<class U, class T, std::size_t N> -struct sp_select_size_deleter<std::allocator<U>, T, N> { - typedef sp_size_array_deleter<T, N> type; +template<class T> +struct sp_use_construct<std::allocator<T> > { + enum { + value = false + }; }; - -template<class A, class T> -struct sp_select_deleter { - typedef sp_array_destroyer<T, - typename sp_bind_allocator<A, T>::type> type; +#else +template<class> +struct sp_use_construct { + enum { + value = false + }; }; +#endif -template<class U, class T> -struct sp_select_deleter<std::allocator<U>, T> { - typedef sp_array_deleter<T> type; -}; -#else -template<class, class T, std::size_t N> -struct sp_select_size_deleter { - typedef sp_size_array_deleter<T, N> type; +template<class T, class U> +struct sp_array_alignment { + enum { + value = sp_max_size<boost::alignment_of<T>::value, + boost::alignment_of<U>::value>::value + }; }; -template<class, class T> -struct sp_select_deleter { - typedef sp_array_deleter<T> type; +template<class T, class U> +struct sp_array_offset { + enum { + value = sp_align_up<sizeof(T), sp_array_alignment<T, U>::value>::value + }; }; -#endif -template<class P, class T, std::size_t N, class A> -class sp_counted_impl_pda<P, sp_size_array_deleter<T, N>, A> - : public sp_counted_base { -public: - typedef sp_size_array_deleter<T, N> deleter_type; +template<class T, class U> +struct sp_array_storage { + enum { + value = sp_array_alignment<T, U>::value + }; + typedef typename boost::type_with_alignment<value>::type type; +}; -private: - typedef sp_counted_impl_pda<P, deleter_type, A> type; - typedef typename sp_bind_allocator<A, type>::type deallocator; +template<class T, class U> +inline U* +sp_array_start(void* base) BOOST_SP_NOEXCEPT +{ + enum { + size = sp_array_offset<T, U>::value + }; + return reinterpret_cast<U*>(static_cast<char*>(base) + size); +} -public: - sp_counted_impl_pda(P, const deleter_type&, const A& allocator) - : deleter_(allocator), - allocator_(allocator) { } +template<class A, class T> +class sp_array_creator { + typedef typename A::value_type scalar; - sp_counted_impl_pda(P, const A& allocator) - : deleter_(allocator) { } + enum { + offset = sp_array_offset<T, scalar>::value + }; - void dispose() { - deleter_(0); - } + typedef typename sp_array_storage<T, scalar>::type type; - void destroy() { - deallocator allocator(allocator_); - this->~type(); - allocator.deallocate(this, 1); - } +public: + template<class U> + sp_array_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT + : other_(other), + size_(sp_objects<type>(offset + sizeof(scalar) * size)) { } - void* get_deleter(const sp_typeinfo&) { - return &reinterpret_cast<char&>(deleter_); + T* create() { + return reinterpret_cast<T*>(other_.allocate(size_)); } - void* get_untyped_deleter() { - return &reinterpret_cast<char&>(deleter_); + void destroy(T* base) { + other_.deallocate(reinterpret_cast<type*>(base), size_); } private: - deleter_type deleter_; - A allocator_; + typename sp_bind_allocator<A, type>::type other_; + std::size_t size_; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) -template<class P, class T, std::size_t N, class U, class A> -class sp_counted_impl_pda<P, sp_size_array_destroyer<T, N, U>, A> - : public sp_counted_base { -public: - typedef sp_size_array_destroyer<T, N, U> deleter_type; +struct sp_default { }; -private: - typedef sp_counted_impl_pda<P, deleter_type, A> type; - typedef typename sp_bind_allocator<A, type>::type deallocator; +template<class T, bool E = sp_use_construct<T>::value> +class sp_array_base + : public sp_counted_base { + typedef typename T::type allocator; public: - sp_counted_impl_pda(P, const deleter_type&, const A& allocator) - : deleter_(allocator) { } - - sp_counted_impl_pda(P, const A& allocator) - : deleter_(allocator) { } + typedef typename allocator::value_type type; - void dispose() { - deleter_(0); + template<class A> + sp_array_base(const A& other, std::size_t size, type* start) + : state_(other, size) { + sp_array_construct<E>(state_.allocator(), start, state_.size()); } - void destroy() { - deallocator allocator(deleter_.allocator()); - this->~type(); - allocator.deallocate(this, 1); + template<class A> + sp_array_base(const A& other, std::size_t size, const type* list, + std::size_t count, type* start) + : state_(other, size) { + sp_array_construct<E>(state_.allocator(), start, state_.size(), list, + count); } - void* get_deleter(const sp_typeinfo&) { - return &reinterpret_cast<char&>(deleter_); + template<class A> + sp_array_base(sp_default, const A& other, std::size_t size, type* start) + : state_(other, size) { + sp_array_default(state_.allocator(), start, state_.size()); } - void* get_untyped_deleter() { - return &reinterpret_cast<char&>(deleter_); + T& state() BOOST_SP_NOEXCEPT { + return state_; } -private: - deleter_type deleter_; -}; -#endif - -template<class P, class T, class A> -class sp_counted_impl_pda<P, sp_array_deleter<T>, - sp_array_allocator<T, A> > - : public sp_counted_base { -public: - typedef sp_array_deleter<T> deleter_type; - typedef sp_array_allocator<T, A> allocator_type; - -private: - typedef sp_counted_impl_pda<P, deleter_type, allocator_type> type; - typedef sp_array_allocator<T, - typename sp_bind_allocator<A, type>::type> deallocator; - -public: - sp_counted_impl_pda(P, const deleter_type&, - const allocator_type& allocator) - : deleter_(allocator), - allocator_(allocator.allocator()) { } - - sp_counted_impl_pda(P, const allocator_type& allocator) - : deleter_(allocator), - allocator_(allocator.allocator()) { } + virtual void dispose() { + sp_array_destroy<E>(state_.allocator(), + sp_array_start<sp_array_base, type>(this), state_.size()); + } - void dispose() { - deleter_(0); + virtual void destroy() { + sp_array_creator<allocator, sp_array_base> other(state_.allocator(), + state_.size()); + this->~sp_array_base(); + other.destroy(this); } - void destroy() { - deallocator allocator(allocator_, deleter_.size()); - this->~type(); - allocator.deallocate(this, 1); + virtual void* get_deleter(const sp_typeinfo&) { + return 0; } - void* get_deleter(const sp_typeinfo&) { - return &reinterpret_cast<char&>(deleter_); + virtual void* get_local_deleter(const sp_typeinfo&) { + return 0; } - void* get_untyped_deleter() { - return &reinterpret_cast<char&>(deleter_); + virtual void* get_untyped_deleter() { + return 0; } private: - deleter_type deleter_; - A allocator_; + T state_; }; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) -template<class P, class T, class U, class A> -class sp_counted_impl_pda<P, sp_array_destroyer<T, U>, - sp_array_allocator<T, A> > - : public sp_counted_base { -public: - typedef sp_array_destroyer<T, U> deleter_type; - typedef sp_array_allocator<T, A> allocator_type; - -private: - typedef sp_counted_impl_pda<P, deleter_type, allocator_type> type; - typedef sp_array_allocator<T, - typename sp_bind_allocator<A, type>::type> deallocator; - +template<class A, class T> +struct sp_array_result { public: - sp_counted_impl_pda(P, const deleter_type&, - const allocator_type& allocator) - : deleter_(allocator) { } - - sp_counted_impl_pda(P, const allocator_type& allocator) - : deleter_(allocator) { } - - void dispose() { - deleter_(0); - } + template<class U> + sp_array_result(const U& other, std::size_t size) + : creator_(other, size), + result_(creator_.create()) { } - void destroy() { - deallocator allocator(deleter_.allocator(), deleter_.size()); - this->~type(); - allocator.deallocate(this, 1); + ~sp_array_result() { + if (result_) { + creator_.destroy(result_); + } } - void* get_deleter(const sp_typeinfo&) { - return &reinterpret_cast<char&>(deleter_); + T* get() const { + return result_; } - void* get_untyped_deleter() { - return &reinterpret_cast<char&>(deleter_); + void release() { + result_ = 0; } private: - deleter_type deleter_; + sp_array_result(const sp_array_result&); + sp_array_result& operator=(const sp_array_result&); + + sp_array_creator<A, T> creator_; + T* result_; }; -#endif } /* detail */ template<class T, class A> -inline typename detail::sp_if_size_array<T>::type -allocate_shared(const A& allocator) +inline typename detail::sp_if_array<T>::type +allocate_shared(const A& allocator, std::size_t count) { typedef typename detail::sp_array_element<T>::type type; typedef typename detail::sp_array_scalar<T>::type scalar; - typedef typename detail::sp_select_size_deleter<A, scalar, - detail::sp_array_count<T>::value>::type deleter; - shared_ptr<T> result(static_cast<type*>(0), - detail::sp_inplace_tag<deleter>(), allocator); - deleter* state = detail::sp_get_deleter<deleter>(result); - void* start = state->construct(); - return shared_ptr<T>(result, static_cast<type*>(start)); + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_array_state<other> state; + typedef detail::sp_array_base<state> base; + std::size_t size = count * detail::sp_array_count<type>::value; + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } template<class T, class A> inline typename detail::sp_if_size_array<T>::type -allocate_shared(const A& allocator, - const typename detail::sp_array_element<T>::type& value) +allocate_shared(const A& allocator) { + enum { + size = detail::sp_array_count<T>::value + }; typedef typename detail::sp_array_element<T>::type type; typedef typename detail::sp_array_scalar<T>::type scalar; - typedef typename detail::sp_select_size_deleter<A, scalar, - detail::sp_array_count<T>::value>::type deleter; - shared_ptr<T> result(static_cast<type*>(0), - detail::sp_inplace_tag<deleter>(), allocator); - deleter* state = detail::sp_get_deleter<deleter>(result); - void* start = state->construct(reinterpret_cast<const - scalar*>(&value), detail::sp_array_count<type>::value); - return shared_ptr<T>(result, static_cast<type*>(start)); + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_size_array_state<other, size> state; + typedef detail::sp_array_base<state> base; + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } template<class T, class A> -inline typename detail::sp_if_size_array<T>::type -allocate_shared_noinit(const A& allocator) +inline typename detail::sp_if_array<T>::type +allocate_shared(const A& allocator, std::size_t count, + const typename detail::sp_array_element<T>::type& value) { typedef typename detail::sp_array_element<T>::type type; typedef typename detail::sp_array_scalar<T>::type scalar; - typedef detail::sp_size_array_deleter<scalar, - detail::sp_array_count<T>::value> deleter; - shared_ptr<T> result(static_cast<type*>(0), - detail::sp_inplace_tag<deleter>(), allocator); - deleter* state = detail::sp_get_deleter<deleter>(result); - void* start = state->construct_default(); - return shared_ptr<T>(result, static_cast<type*>(start)); + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_array_state<other> state; + typedef detail::sp_array_base<state> base; + std::size_t size = count * detail::sp_array_count<type>::value; + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, + reinterpret_cast<const scalar*>(&value), + detail::sp_array_count<type>::value, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } template<class T, class A> -inline typename detail::sp_if_array<T>::type -allocate_shared(const A& allocator, std::size_t count) +inline typename detail::sp_if_size_array<T>::type +allocate_shared(const A& allocator, + const typename detail::sp_array_element<T>::type& value) { + enum { + size = detail::sp_array_count<T>::value + }; typedef typename detail::sp_array_element<T>::type type; typedef typename detail::sp_array_scalar<T>::type scalar; - typedef typename detail::sp_select_deleter<A, scalar>::type deleter; - std::size_t size = count * detail::sp_array_count<type>::value; - void* start; - shared_ptr<T> result(static_cast<type*>(0), - detail::sp_inplace_tag<deleter>(), - detail::sp_array_allocator<scalar, A>(allocator, size, &start)); - deleter* state = detail::sp_get_deleter<deleter>(result); - state->construct(static_cast<scalar*>(start)); - return shared_ptr<T>(result, static_cast<type*>(start)); + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_size_array_state<other, size> state; + typedef detail::sp_array_base<state> base; + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, + reinterpret_cast<const scalar*>(&value), + detail::sp_array_count<type>::value, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } template<class T, class A> inline typename detail::sp_if_array<T>::type -allocate_shared(const A& allocator, std::size_t count, - const typename detail::sp_array_element<T>::type& value) +allocate_shared_noinit(const A& allocator, std::size_t count) { typedef typename detail::sp_array_element<T>::type type; typedef typename detail::sp_array_scalar<T>::type scalar; - typedef typename detail::sp_select_deleter<A, scalar>::type deleter; + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_array_state<other> state; + typedef detail::sp_array_base<state, false> base; std::size_t size = count * detail::sp_array_count<type>::value; - void* start; - shared_ptr<T> result(static_cast<type*>(0), - detail::sp_inplace_tag<deleter>(), - detail::sp_array_allocator<scalar, A>(allocator, size, &start)); - deleter* state = detail::sp_get_deleter<deleter>(result); - state->construct(static_cast<scalar*>(start), - reinterpret_cast<const scalar*>(&value), - detail::sp_array_count<type>::value); - return shared_ptr<T>(result, static_cast<type*>(start)); + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator, + size, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } template<class T, class A> -inline typename detail::sp_if_array<T>::type -allocate_shared_noinit(const A& allocator, std::size_t count) +inline typename detail::sp_if_size_array<T>::type +allocate_shared_noinit(const A& allocator) { + enum { + size = detail::sp_array_count<T>::value + }; typedef typename detail::sp_array_element<T>::type type; typedef typename detail::sp_array_scalar<T>::type scalar; - typedef detail::sp_array_deleter<scalar> deleter; - std::size_t size = count * detail::sp_array_count<type>::value; - void* start; - shared_ptr<T> result(static_cast<type*>(0), - detail::sp_inplace_tag<deleter>(), - detail::sp_array_allocator<scalar, A>(allocator, size, &start)); - deleter* state = detail::sp_get_deleter<deleter>(result); - state->construct_default(static_cast<scalar*>(start)); - return shared_ptr<T>(result, static_cast<type*>(start)); + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_size_array_state<other, size> state; + typedef detail::sp_array_base<state, false> base; + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator, + size, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } } /* boost */ diff --git a/boost/smart_ptr/atomic_shared_ptr.hpp b/boost/smart_ptr/atomic_shared_ptr.hpp new file mode 100644 index 0000000000..d1efa8e280 --- /dev/null +++ b/boost/smart_ptr/atomic_shared_ptr.hpp @@ -0,0 +1,183 @@ +#ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED + +// +// atomic_shared_ptr.hpp +// +// Copyright 2017 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/smart_ptr/ for documentation. +// + +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/smart_ptr/detail/spinlock.hpp> +#include <cstring> + +namespace boost +{ + +template<class T> class atomic_shared_ptr +{ +private: + + boost::shared_ptr<T> p_; + + mutable boost::detail::spinlock l_; + + atomic_shared_ptr(const atomic_shared_ptr&); + atomic_shared_ptr& operator=(const atomic_shared_ptr&); + +private: + + bool compare_exchange( shared_ptr<T>& v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT + { + l_.lock(); + + if( p_._internal_equiv( v ) ) + { + p_.swap( w ); + + l_.unlock(); + return true; + } + else + { + shared_ptr<T> tmp( p_ ); + + l_.unlock(); + + tmp.swap( v ); + return false; + } + } + +public: + +#if !defined( BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX ) && !defined( BOOST_NO_CXX11_CONSTEXPR ) + + constexpr atomic_shared_ptr() BOOST_SP_NOEXCEPT: l_ BOOST_DETAIL_SPINLOCK_INIT + { + } + +#else + + atomic_shared_ptr() BOOST_SP_NOEXCEPT + { + boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT; + std::memcpy( &l_, &init, sizeof( init ) ); + } + +#endif + + atomic_shared_ptr( shared_ptr<T> p ) BOOST_SP_NOEXCEPT +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + : p_( std::move( p ) ) +#else + : p_( p ) +#endif + { + boost::detail::spinlock init = BOOST_DETAIL_SPINLOCK_INIT; + std::memcpy( &l_, &init, sizeof( init ) ); + } + + atomic_shared_ptr& operator=( shared_ptr<T> r ) BOOST_SP_NOEXCEPT + { + boost::detail::spinlock::scoped_lock lock( l_ ); + p_.swap( r ); + + return *this; + } + + BOOST_CONSTEXPR bool is_lock_free() const BOOST_SP_NOEXCEPT + { + return false; + } + + shared_ptr<T> load( int = 0 ) const BOOST_SP_NOEXCEPT + { + boost::detail::spinlock::scoped_lock lock( l_ ); + return p_; + } + + operator shared_ptr<T>() const BOOST_SP_NOEXCEPT + { + boost::detail::spinlock::scoped_lock lock( l_ ); + return p_; + } + + void store( shared_ptr<T> r, int = 0 ) BOOST_SP_NOEXCEPT + { + boost::detail::spinlock::scoped_lock lock( l_ ); + p_.swap( r ); + } + + shared_ptr<T> exchange( shared_ptr<T> r, int = 0 ) BOOST_SP_NOEXCEPT + { + { + boost::detail::spinlock::scoped_lock lock( l_ ); + p_.swap( r ); + } + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + return std::move( r ); + +#else + + return r; + +#endif + } + + bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT + { + return compare_exchange( v, w ); + } + + bool compare_exchange_weak( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT + { + return compare_exchange( v, w ); + } + + bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int, int ) BOOST_SP_NOEXCEPT + { + return compare_exchange( v, w ); + } + + bool compare_exchange_strong( shared_ptr<T>& v, const shared_ptr<T>& w, int = 0 ) BOOST_SP_NOEXCEPT + { + return compare_exchange( v, w ); + } + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT + { + return compare_exchange( v, std::move( w ) ); + } + + bool compare_exchange_weak( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) BOOST_SP_NOEXCEPT + { + return compare_exchange( v, std::move( w ) ); + } + + bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int, int ) BOOST_SP_NOEXCEPT + { + return compare_exchange( v, std::move( w ) ); + } + + bool compare_exchange_strong( shared_ptr<T>& v, shared_ptr<T>&& w, int = 0 ) BOOST_SP_NOEXCEPT + { + return compare_exchange( v, std::move( w ) ); + } + +#endif +}; + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_ATOMIC_SHARED_PTR_HPP_INCLUDED diff --git a/boost/smart_ptr/bad_weak_ptr.hpp b/boost/smart_ptr/bad_weak_ptr.hpp index 582fad8b71..b086be595f 100644 --- a/boost/smart_ptr/bad_weak_ptr.hpp +++ b/boost/smart_ptr/bad_weak_ptr.hpp @@ -17,6 +17,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // +#include <boost/config.hpp> #include <exception> #ifdef __BORLANDC__ @@ -36,7 +37,8 @@ namespace boost # pragma option push -pc #endif -#if defined(__clang__) +#if defined(BOOST_CLANG) +// Intel C++ on Mac defines __clang__ but doesn't support the pragma # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wweak-vtables" #endif @@ -51,7 +53,7 @@ public: } }; -#if defined(__clang__) +#if defined(BOOST_CLANG) # pragma clang diagnostic pop #endif diff --git a/boost/smart_ptr/detail/atomic_count_gcc.hpp b/boost/smart_ptr/detail/atomic_count_gcc.hpp index 54807e944e..df7e32365f 100644 --- a/boost/smart_ptr/detail/atomic_count_gcc.hpp +++ b/boost/smart_ptr/detail/atomic_count_gcc.hpp @@ -9,7 +9,7 @@ // http://gcc.gnu.org/onlinedocs/porting/Thread-safety.html // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. -// Copyright (c) 2002 Lars Gullik Bjønnes <larsbj@lyx.org> +// Copyright (c) 2002 Lars Gullik Bjønnes <larsbj@lyx.org> // Copyright 2003-2005 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See diff --git a/boost/smart_ptr/detail/local_counted_base.hpp b/boost/smart_ptr/detail/local_counted_base.hpp new file mode 100644 index 0000000000..398b46dd1a --- /dev/null +++ b/boost/smart_ptr/detail/local_counted_base.hpp @@ -0,0 +1,146 @@ +#ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/local_counted_base.hpp +// +// Copyright 2017 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/smart_ptr/ for documentation. + +#include <boost/smart_ptr/detail/shared_count.hpp> +#include <boost/config.hpp> +#include <utility> + +namespace boost +{ + +namespace detail +{ + +class local_counted_base +{ +private: + + local_counted_base & operator= ( local_counted_base const & ); + +private: + + // not 'int' or 'unsigned' to avoid aliasing and enable optimizations + enum count_type { min_ = 0, initial_ = 1, max_ = 2147483647 }; + + count_type local_use_count_; + +public: + + BOOST_CONSTEXPR local_counted_base() BOOST_SP_NOEXCEPT: local_use_count_( initial_ ) + { + } + + BOOST_CONSTEXPR local_counted_base( local_counted_base const & ) BOOST_SP_NOEXCEPT: local_use_count_( initial_ ) + { + } + + virtual ~local_counted_base() /*BOOST_SP_NOEXCEPT*/ + { + } + + virtual void local_cb_destroy() BOOST_SP_NOEXCEPT = 0; + + virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT = 0; + + void add_ref() BOOST_SP_NOEXCEPT + { +#if defined( __has_builtin ) +# if __has_builtin( __builtin_assume ) + + __builtin_assume( local_use_count_ >= 1 ); + +# endif +#endif + + local_use_count_ = static_cast<count_type>( local_use_count_ + 1 ); + } + + void release() BOOST_SP_NOEXCEPT + { + local_use_count_ = static_cast<count_type>( local_use_count_ - 1 ); + + if( local_use_count_ == 0 ) + { + local_cb_destroy(); + } + } + + long local_use_count() const BOOST_SP_NOEXCEPT + { + return local_use_count_; + } +}; + +class local_counted_impl: public local_counted_base +{ +private: + + local_counted_impl( local_counted_impl const & ); + +private: + + shared_count pn_; + +public: + + explicit local_counted_impl( shared_count const& pn ): pn_( pn ) + { + } + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + explicit local_counted_impl( shared_count && pn ): pn_( std::move(pn) ) + { + } + +#endif + + virtual void local_cb_destroy() BOOST_SP_NOEXCEPT + { + delete this; + } + + virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT + { + return pn_; + } +}; + +class local_counted_impl_em: public local_counted_base +{ +public: + + shared_count pn_; + + virtual void local_cb_destroy() BOOST_SP_NOEXCEPT + { + shared_count().swap( pn_ ); + } + + virtual boost::detail::shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT + { + return pn_; + } +}; + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_COUNTED_BASE_HPP_INCLUDED diff --git a/boost/smart_ptr/detail/local_sp_deleter.hpp b/boost/smart_ptr/detail/local_sp_deleter.hpp new file mode 100644 index 0000000000..7d04f1dc52 --- /dev/null +++ b/boost/smart_ptr/detail/local_sp_deleter.hpp @@ -0,0 +1,91 @@ +#ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// detail/local_sp_deleter.hpp +// +// Copyright 2017 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/smart_ptr/ for documentation. + +#include <boost/smart_ptr/detail/local_counted_base.hpp> +#include <boost/config.hpp> + +namespace boost +{ + +namespace detail +{ + +template<class D> class local_sp_deleter: public local_counted_impl_em +{ +private: + + D d_; + +public: + + local_sp_deleter(): d_() + { + } + + explicit local_sp_deleter( D const& d ) BOOST_SP_NOEXCEPT: d_( d ) + { + } + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + explicit local_sp_deleter( D&& d ) BOOST_SP_NOEXCEPT: d_( std::move(d) ) + { + } + +#endif + + D& deleter() + { + return d_; + } + + template<class Y> void operator()( Y* p ) BOOST_SP_NOEXCEPT + { + d_( p ); + } + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + void operator()( boost::detail::sp_nullptr_t p ) BOOST_SP_NOEXCEPT + { + d_( p ); + } + +#endif +}; + +template<> class local_sp_deleter<void> +{ +}; + +template<class D> D * get_local_deleter( local_sp_deleter<D> * p ) +{ + return &p->deleter(); +} + +inline void * get_local_deleter( local_sp_deleter<void> * /*p*/ ) +{ + return 0; +} + +} // namespace detail + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_LOCAL_SP_DELETER_HPP_INCLUDED diff --git a/boost/smart_ptr/detail/lwm_win32_cs.hpp b/boost/smart_ptr/detail/lwm_win32_cs.hpp index a93cf09208..7d3e156166 100644 --- a/boost/smart_ptr/detail/lwm_win32_cs.hpp +++ b/boost/smart_ptr/detail/lwm_win32_cs.hpp @@ -21,7 +21,13 @@ #include <boost/predef.h> #ifdef BOOST_USE_WINDOWS_H -# include <windows.h> + +#include <windows.h> + +#else + +struct _RTL_CRITICAL_SECTION; + #endif namespace boost @@ -47,13 +53,13 @@ struct critical_section }; #if BOOST_PLAT_WINDOWS_RUNTIME -extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSectionEx(critical_section *, unsigned long, unsigned long); +extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSectionEx(::_RTL_CRITICAL_SECTION *, unsigned long, unsigned long); #else -extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall InitializeCriticalSection(::_RTL_CRITICAL_SECTION *); #endif -extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(critical_section *); -extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(critical_section *); -extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(critical_section *); +extern "C" __declspec(dllimport) void __stdcall EnterCriticalSection(::_RTL_CRITICAL_SECTION *); +extern "C" __declspec(dllimport) void __stdcall LeaveCriticalSection(::_RTL_CRITICAL_SECTION *); +extern "C" __declspec(dllimport) void __stdcall DeleteCriticalSection(::_RTL_CRITICAL_SECTION *); #else @@ -75,15 +81,15 @@ public: lightweight_mutex() { #if BOOST_PLAT_WINDOWS_RUNTIME - InitializeCriticalSectionEx(&cs_, 4000, 0); + boost::detail::InitializeCriticalSectionEx(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&cs_), 4000, 0); #else - InitializeCriticalSection(&cs_); + boost::detail::InitializeCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&cs_)); #endif } ~lightweight_mutex() { - DeleteCriticalSection(&cs_); + boost::detail::DeleteCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&cs_)); } class scoped_lock; @@ -102,12 +108,12 @@ public: explicit scoped_lock(lightweight_mutex & m): m_(m) { - EnterCriticalSection(&m_.cs_); + boost::detail::EnterCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_.cs_)); } ~scoped_lock() { - LeaveCriticalSection(&m_.cs_); + boost::detail::LeaveCriticalSection(reinterpret_cast< ::_RTL_CRITICAL_SECTION* >(&m_.cs_)); } }; }; diff --git a/boost/smart_ptr/detail/operator_bool.hpp b/boost/smart_ptr/detail/operator_bool.hpp index c0289b870b..f9c5ef6803 100644 --- a/boost/smart_ptr/detail/operator_bool.hpp +++ b/boost/smart_ptr/detail/operator_bool.hpp @@ -9,14 +9,14 @@ #if !defined( BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS ) && !defined( BOOST_NO_CXX11_NULLPTR )\ && !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130)) - explicit operator bool () const BOOST_NOEXCEPT + explicit operator bool () const BOOST_SP_NOEXCEPT { return px != 0; } #elif ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) - operator bool () const BOOST_NOEXCEPT + operator bool () const BOOST_SP_NOEXCEPT { return px != 0; } @@ -29,7 +29,7 @@ typedef void (*unspecified_bool_type)( this_type*** ); - operator unspecified_bool_type() const BOOST_NOEXCEPT + operator unspecified_bool_type() const BOOST_SP_NOEXCEPT { return px == 0? 0: unspecified_bool; } @@ -41,7 +41,7 @@ typedef element_type * (this_type::*unspecified_bool_type)() const; - operator unspecified_bool_type() const BOOST_NOEXCEPT + operator unspecified_bool_type() const BOOST_SP_NOEXCEPT { return px == 0? 0: &this_type::get; } @@ -50,7 +50,7 @@ typedef element_type * this_type::*unspecified_bool_type; - operator unspecified_bool_type() const BOOST_NOEXCEPT + operator unspecified_bool_type() const BOOST_SP_NOEXCEPT { return px == 0? 0: &this_type::px; } @@ -58,7 +58,7 @@ #endif // operator! is redundant, but some compilers need it - bool operator! () const BOOST_NOEXCEPT + bool operator! () const BOOST_SP_NOEXCEPT { return px == 0; } diff --git a/boost/smart_ptr/detail/shared_count.hpp b/boost/smart_ptr/detail/shared_count.hpp index 9813842300..ae7d0fb46f 100644 --- a/boost/smart_ptr/detail/shared_count.hpp +++ b/boost/smart_ptr/detail/shared_count.hpp @@ -54,7 +54,7 @@ namespace boost namespace movelib { - template< class T, class D > class unique_ptr; +template< class T, class D > class unique_ptr; } // namespace movelib @@ -118,7 +118,14 @@ private: public: - shared_count(): pi_(0) // nothrow + BOOST_CONSTEXPR shared_count(): pi_(0) // nothrow +#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) + , id_(shared_count_id) +#endif + { + } + + BOOST_CONSTEXPR explicit shared_count( sp_counted_base * pi ): pi_( pi ) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(shared_count_id) #endif @@ -496,6 +503,11 @@ public: return pi_? pi_->get_deleter( ti ): 0; } + void * get_local_deleter( sp_typeinfo const & ti ) const + { + return pi_? pi_->get_local_deleter( ti ): 0; + } + void * get_untyped_deleter() const { return pi_? pi_->get_untyped_deleter(): 0; @@ -517,7 +529,7 @@ private: public: - weak_count(): pi_(0) // nothrow + BOOST_CONSTEXPR weak_count(): pi_(0) // nothrow #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) , id_(weak_count_id) #endif diff --git a/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp b/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp index cebc243d2e..ec6f6ee184 100644 --- a/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp @@ -104,6 +104,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_aix.hpp b/boost/smart_ptr/detail/sp_counted_base_aix.hpp index fe6c727e38..ce8ee686ba 100644 --- a/boost/smart_ptr/detail/sp_counted_base_aix.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_aix.hpp @@ -96,6 +96,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_clang.hpp b/boost/smart_ptr/detail/sp_counted_base_clang.hpp index 75984959d3..8b3bfad9b6 100644 --- a/boost/smart_ptr/detail/sp_counted_base_clang.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_clang.hpp @@ -98,6 +98,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp b/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp index 6c268e8921..065f7c3d14 100644 --- a/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp @@ -124,6 +124,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp b/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp index 81eba6f178..3a3d4d4119 100644 --- a/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp @@ -112,6 +112,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp index f6e3904157..6c3cce8d44 100644 --- a/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp @@ -111,6 +111,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp index 545c8ae4fc..76ac2a612d 100644 --- a/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp @@ -135,6 +135,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp index 2e5bc0e853..0fb807488a 100644 --- a/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp @@ -135,6 +135,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp index c6d20ce7ea..b8bb707f1b 100644 --- a/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp @@ -120,6 +120,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp b/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp index 173dce5c81..3d2dd61ed6 100644 --- a/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp @@ -127,6 +127,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_nt.hpp b/boost/smart_ptr/detail/sp_counted_base_nt.hpp index 5c901f9d16..dea905c905 100644 --- a/boost/smart_ptr/detail/sp_counted_base_nt.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_nt.hpp @@ -59,6 +59,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_pt.hpp b/boost/smart_ptr/detail/sp_counted_base_pt.hpp index a16d2d8652..85f2563d5d 100644 --- a/boost/smart_ptr/detail/sp_counted_base_pt.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_pt.hpp @@ -71,6 +71,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp b/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp index 56ed79fa97..7b5f9178a6 100644 --- a/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp @@ -115,6 +115,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_solaris.hpp b/boost/smart_ptr/detail/sp_counted_base_solaris.hpp index 0e05fef4cb..0db9c6cbd5 100644 --- a/boost/smart_ptr/detail/sp_counted_base_solaris.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_solaris.hpp @@ -62,6 +62,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_spin.hpp b/boost/smart_ptr/detail/sp_counted_base_spin.hpp index 77734e727d..faf503ad57 100644 --- a/boost/smart_ptr/detail/sp_counted_base_spin.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_spin.hpp @@ -84,6 +84,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp b/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp index cab8453591..7a188f8a66 100644 --- a/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp @@ -90,6 +90,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_sync.hpp b/boost/smart_ptr/detail/sp_counted_base_sync.hpp index fafed0e72e..d2138e7c26 100644 --- a/boost/smart_ptr/detail/sp_counted_base_sync.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_sync.hpp @@ -109,6 +109,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp b/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp index 162f309b56..f2de3b02d8 100644 --- a/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp @@ -104,6 +104,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_base_w32.hpp b/boost/smart_ptr/detail/sp_counted_base_w32.hpp index 4ba509c6cd..960e42e128 100644 --- a/boost/smart_ptr/detail/sp_counted_base_w32.hpp +++ b/boost/smart_ptr/detail/sp_counted_base_w32.hpp @@ -67,6 +67,7 @@ public: } virtual void * get_deleter( sp_typeinfo const & ti ) = 0; + virtual void * get_local_deleter( sp_typeinfo const & ti ) = 0; virtual void * get_untyped_deleter() = 0; void add_ref_copy() diff --git a/boost/smart_ptr/detail/sp_counted_impl.hpp b/boost/smart_ptr/detail/sp_counted_impl.hpp index b29769e3af..fa2f75eb1a 100644 --- a/boost/smart_ptr/detail/sp_counted_impl.hpp +++ b/boost/smart_ptr/detail/sp_counted_impl.hpp @@ -26,6 +26,7 @@ #include <boost/checked_delete.hpp> #include <boost/smart_ptr/detail/sp_counted_base.hpp> +#include <boost/core/addressof.hpp> #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) #include <boost/smart_ptr/detail/quick_allocator.hpp> @@ -50,6 +51,19 @@ void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn ); namespace detail { +// get_local_deleter + +template<class D> class local_sp_deleter; + +template<class D> D * get_local_deleter( D * /*p*/ ) +{ + return 0; +} + +template<class D> D * get_local_deleter( local_sp_deleter<D> * p ); + +// + template<class X> class sp_counted_impl_p: public sp_counted_base { private: @@ -83,6 +97,11 @@ public: return 0; } + virtual void * get_local_deleter( sp_typeinfo const & ) + { + return 0; + } + virtual void * get_untyped_deleter() { return 0; @@ -158,6 +177,11 @@ public: return ti == BOOST_SP_TYPEID(D)? &reinterpret_cast<char&>( del ): 0; } + virtual void * get_local_deleter( sp_typeinfo const & ti ) + { + return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( del ) ): 0; + } + virtual void * get_untyped_deleter() { return &reinterpret_cast<char&>( del ); @@ -246,6 +270,11 @@ public: return ti == BOOST_SP_TYPEID( D )? &reinterpret_cast<char&>( d_ ): 0; } + virtual void * get_local_deleter( sp_typeinfo const & ti ) + { + return ti == BOOST_SP_TYPEID(D)? boost::detail::get_local_deleter( boost::addressof( d_ ) ): 0; + } + virtual void * get_untyped_deleter() { return &reinterpret_cast<char&>( d_ ); diff --git a/boost/smart_ptr/detail/sp_noexcept.hpp b/boost/smart_ptr/detail/sp_noexcept.hpp index 6818dce38d..1287ba4952 100644 --- a/boost/smart_ptr/detail/sp_noexcept.hpp +++ b/boost/smart_ptr/detail/sp_noexcept.hpp @@ -9,7 +9,7 @@ // detail/sp_noexcept.hpp // -// Copyright 2016 Peter Dimov +// Copyright 2016, 2017 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at @@ -17,13 +17,31 @@ #include <boost/config.hpp> +// BOOST_SP_NOEXCEPT + #if defined( BOOST_MSVC ) && BOOST_MSVC >= 1700 && BOOST_MSVC < 1900 -#define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT_OR_NOTHROW +# define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT_OR_NOTHROW + +#else + +# define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT + +#endif + +// BOOST_SP_NOEXCEPT_WITH_ASSERT + +#if defined(BOOST_DISABLE_ASSERTS) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && defined(NDEBUG) ) + +# define BOOST_SP_NOEXCEPT_WITH_ASSERT BOOST_SP_NOEXCEPT + +#elif defined(BOOST_ENABLE_ASSERT_HANDLER) || ( defined(BOOST_ENABLE_ASSERT_DEBUG_HANDLER) && !defined(NDEBUG) ) + +# define BOOST_SP_NOEXCEPT_WITH_ASSERT #else -#define BOOST_SP_NOEXCEPT BOOST_NOEXCEPT +# define BOOST_SP_NOEXCEPT_WITH_ASSERT BOOST_SP_NOEXCEPT #endif diff --git a/boost/smart_ptr/detail/yield_k.hpp b/boost/smart_ptr/detail/yield_k.hpp index 44d1836478..f8ca6b6467 100644 --- a/boost/smart_ptr/detail/yield_k.hpp +++ b/boost/smart_ptr/detail/yield_k.hpp @@ -33,7 +33,7 @@ // BOOST_SMT_PAUSE -#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) +#if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_IX86) || defined(_M_X64) ) && !defined(__c2__) extern "C" void _mm_pause(); diff --git a/boost/smart_ptr/enable_shared_from_this.hpp b/boost/smart_ptr/enable_shared_from_this.hpp index 642403a0a3..fc4de0b571 100644 --- a/boost/smart_ptr/enable_shared_from_this.hpp +++ b/boost/smart_ptr/enable_shared_from_this.hpp @@ -10,7 +10,7 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt // -// http://www.boost.org/libs/smart_ptr/enable_shared_from_this.html +// See http://www.boost.org/libs/smart_ptr/ for documentation. // #include <boost/smart_ptr/weak_ptr.hpp> @@ -26,11 +26,11 @@ template<class T> class enable_shared_from_this { protected: - enable_shared_from_this() BOOST_SP_NOEXCEPT + BOOST_CONSTEXPR enable_shared_from_this() BOOST_SP_NOEXCEPT { } - enable_shared_from_this(enable_shared_from_this const &) BOOST_SP_NOEXCEPT + BOOST_CONSTEXPR enable_shared_from_this(enable_shared_from_this const &) BOOST_SP_NOEXCEPT { } @@ -59,12 +59,12 @@ public: return p; } - weak_ptr<T> weak_from_this() BOOST_NOEXCEPT + weak_ptr<T> weak_from_this() BOOST_SP_NOEXCEPT { return weak_this_; } - weak_ptr<T const> weak_from_this() const BOOST_NOEXCEPT + weak_ptr<T const> weak_from_this() const BOOST_SP_NOEXCEPT { return weak_this_; } @@ -72,7 +72,7 @@ public: public: // actually private, but avoids compiler template friendship issues // Note: invoked automatically by shared_ptr; do not call - template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const + template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const BOOST_SP_NOEXCEPT { if( weak_this_.expired() ) { diff --git a/boost/smart_ptr/intrusive_ptr.hpp b/boost/smart_ptr/intrusive_ptr.hpp index 0e46212165..0ab075d367 100644 --- a/boost/smart_ptr/intrusive_ptr.hpp +++ b/boost/smart_ptr/intrusive_ptr.hpp @@ -6,11 +6,11 @@ // // Copyright (c) 2001, 2002 Peter Dimov // -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // -// See http://www.boost.org/libs/smart_ptr/intrusive_ptr.html for documentation. +// See http://www.boost.org/libs/smart_ptr/ for documentation. // #include <boost/config.hpp> @@ -141,7 +141,7 @@ public: } template<class U> - intrusive_ptr & operator=(intrusive_ptr<U> && rhs) BOOST_NOEXCEPT + intrusive_ptr & operator=(intrusive_ptr<U> && rhs) BOOST_SP_NOEXCEPT { this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this); return *this; @@ -161,7 +161,7 @@ public: return *this; } - void reset() BOOST_NOEXCEPT + void reset() { this_type().swap( *this ); } @@ -176,25 +176,25 @@ public: this_type( rhs, add_ref ).swap( *this ); } - T * get() const BOOST_NOEXCEPT + T * get() const BOOST_SP_NOEXCEPT { return px; } - T * detach() BOOST_NOEXCEPT + T * detach() BOOST_SP_NOEXCEPT { T * ret = px; px = 0; return ret; } - T & operator*() const + T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( px != 0 ); return *px; } - T * operator->() const + T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( px != 0 ); return px; @@ -203,7 +203,7 @@ public: // implicit conversion to "bool" #include <boost/smart_ptr/detail/operator_bool.hpp> - void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT + void swap(intrusive_ptr & rhs) BOOST_SP_NOEXCEPT { T * tmp = px; px = rhs.px; @@ -215,32 +215,32 @@ private: T * px; }; -template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) +template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT { return a.get() == b.get(); } -template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) +template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT { return a.get() != b.get(); } -template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b) +template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b) BOOST_SP_NOEXCEPT { return a.get() == b; } -template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b) +template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b) BOOST_SP_NOEXCEPT { return a.get() != b; } -template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b) +template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT { return a == b.get(); } -template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b) +template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT { return a != b.get(); } @@ -249,7 +249,7 @@ template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const // Resolve the ambiguity between our op!= and the one in rel_ops -template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) +template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) BOOST_SP_NOEXCEPT { return a.get() != b.get(); } @@ -258,41 +258,41 @@ template<class T> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_p #if !defined( BOOST_NO_CXX11_NULLPTR ) -template<class T> inline bool operator==( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +template<class T> inline bool operator==( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() == 0; } -template<class T> inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_NOEXCEPT +template<class T> inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT { return p.get() == 0; } -template<class T> inline bool operator!=( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +template<class T> inline bool operator!=( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() != 0; } -template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_NOEXCEPT +template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT { return p.get() != 0; } #endif -template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) +template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) BOOST_SP_NOEXCEPT { return std::less<T *>()(a.get(), b.get()); } -template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) +template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) BOOST_SP_NOEXCEPT { lhs.swap(rhs); } // mem_fn support -template<class T> T * get_pointer(intrusive_ptr<T> const & p) +template<class T> T * get_pointer(intrusive_ptr<T> const & p) BOOST_SP_NOEXCEPT { return p.get(); } @@ -351,7 +351,7 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std:: template< class T > struct hash; -template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p ) +template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT { return boost::hash< T* >()( p.get() ); } diff --git a/boost/smart_ptr/intrusive_ref_counter.hpp b/boost/smart_ptr/intrusive_ref_counter.hpp index b7587ea7a0..c2f918d0a4 100644 --- a/boost/smart_ptr/intrusive_ref_counter.hpp +++ b/boost/smart_ptr/intrusive_ref_counter.hpp @@ -17,6 +17,7 @@ #include <boost/config.hpp> #include <boost/smart_ptr/detail/atomic_count.hpp> +#include <boost/smart_ptr/detail/sp_noexcept.hpp> #ifdef BOOST_HAS_PRAGMA_ONCE #pragma once @@ -45,17 +46,17 @@ struct thread_unsafe_counter { typedef unsigned int type; - static unsigned int load(unsigned int const& counter) BOOST_NOEXCEPT + static unsigned int load(unsigned int const& counter) BOOST_SP_NOEXCEPT { return counter; } - static void increment(unsigned int& counter) BOOST_NOEXCEPT + static void increment(unsigned int& counter) BOOST_SP_NOEXCEPT { ++counter; } - static unsigned int decrement(unsigned int& counter) BOOST_NOEXCEPT + static unsigned int decrement(unsigned int& counter) BOOST_SP_NOEXCEPT { return --counter; } @@ -71,17 +72,17 @@ struct thread_safe_counter { typedef boost::detail::atomic_count type; - static unsigned int load(boost::detail::atomic_count const& counter) BOOST_NOEXCEPT + static unsigned int load(boost::detail::atomic_count const& counter) BOOST_SP_NOEXCEPT { return static_cast< unsigned int >(static_cast< long >(counter)); } - static void increment(boost::detail::atomic_count& counter) BOOST_NOEXCEPT + static void increment(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT { ++counter; } - static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_NOEXCEPT + static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT { return static_cast< unsigned int >(--counter); } @@ -91,9 +92,9 @@ template< typename DerivedT, typename CounterPolicyT = thread_safe_counter > class intrusive_ref_counter; template< typename DerivedT, typename CounterPolicyT > -void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; +void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT; template< typename DerivedT, typename CounterPolicyT > -void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; +void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT; /*! * \brief A reference counter base class @@ -121,7 +122,7 @@ public: * * \post <tt>use_count() == 0</tt> */ - intrusive_ref_counter() BOOST_NOEXCEPT : m_ref_counter(0) + intrusive_ref_counter() BOOST_SP_NOEXCEPT : m_ref_counter(0) { } @@ -130,7 +131,7 @@ public: * * \post <tt>use_count() == 0</tt> */ - intrusive_ref_counter(intrusive_ref_counter const&) BOOST_NOEXCEPT : m_ref_counter(0) + intrusive_ref_counter(intrusive_ref_counter const&) BOOST_SP_NOEXCEPT : m_ref_counter(0) { } @@ -139,12 +140,12 @@ public: * * \post The reference counter is not modified after assignment */ - intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_NOEXCEPT { return *this; } + intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_SP_NOEXCEPT { return *this; } /*! * \return The reference counter */ - unsigned int use_count() const BOOST_NOEXCEPT + unsigned int use_count() const BOOST_SP_NOEXCEPT { return CounterPolicyT::load(m_ref_counter); } @@ -155,18 +156,18 @@ protected: */ BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {}) - friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; - friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT; + friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT; + friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT; }; template< typename DerivedT, typename CounterPolicyT > -inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT +inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT { CounterPolicyT::increment(p->m_ref_counter); } template< typename DerivedT, typename CounterPolicyT > -inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT +inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT { if (CounterPolicyT::decrement(p->m_ref_counter) == 0) delete static_cast< const DerivedT* >(p); diff --git a/boost/smart_ptr/local_shared_ptr.hpp b/boost/smart_ptr/local_shared_ptr.hpp new file mode 100644 index 0000000000..0d1fa0182e --- /dev/null +++ b/boost/smart_ptr/local_shared_ptr.hpp @@ -0,0 +1,684 @@ +#ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED +#define BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED + +// local_shared_ptr.hpp +// +// Copyright 2017 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/smart_ptr/ for documentation. + +#include <boost/smart_ptr/shared_ptr.hpp> + +namespace boost +{ + +template<class T> class local_shared_ptr; + +namespace detail +{ + +template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn ) +{ + boost::detail::sp_assert_convertible< Y, E >(); + + typedef boost::detail::local_sp_deleter< boost::checked_deleter<Y> > D; + + boost::shared_ptr<E> p2( p, D() ); + + D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() ); + + pd->pn_ = p2._internal_count(); + + pn = pd; +} + +template< class E, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[] > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn ) +{ + boost::detail::sp_assert_convertible< Y[], E[] >(); + + typedef boost::detail::local_sp_deleter< boost::checked_array_deleter<E> > D; + + boost::shared_ptr<E[]> p2( p, D() ); + + D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() ); + + pd->pn_ = p2._internal_count(); + + pn = pd; +} + +template< class E, std::size_t N, class Y > inline void lsp_pointer_construct( boost::local_shared_ptr< E[N] > * /*ppx*/, Y * p, boost::detail::local_counted_base * & pn ) +{ + boost::detail::sp_assert_convertible< Y[N], E[N] >(); + + typedef boost::detail::local_sp_deleter< boost::checked_array_deleter<E> > D; + + boost::shared_ptr<E[N]> p2( p, D() ); + + D * pd = static_cast< D * >( p2._internal_get_untyped_deleter() ); + + pd->pn_ = p2._internal_count(); + + pn = pd; +} + +template< class E, class P, class D > inline void lsp_deleter_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, boost::detail::local_counted_base * & pn ) +{ + typedef boost::detail::local_sp_deleter<D> D2; + + boost::shared_ptr<E> p2( p, D2( d ) ); + + D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() ); + + pd->pn_ = p2._internal_count(); + + pn = pd; +} + +template< class E, class P, class D, class A > inline void lsp_allocator_construct( boost::local_shared_ptr< E > * /*ppx*/, P p, D const& d, A const& a, boost::detail::local_counted_base * & pn ) +{ + typedef boost::detail::local_sp_deleter<D> D2; + + boost::shared_ptr<E> p2( p, D2( d ), a ); + + D2 * pd = static_cast< D2 * >( p2._internal_get_untyped_deleter() ); + + pd->pn_ = p2._internal_count(); + + pn = pd; +} + +struct lsp_internal_constructor_tag +{ +}; + +} // namespace detail + +// +// local_shared_ptr +// +// as shared_ptr, but local to a thread. +// reference count manipulations are non-atomic. +// + +template<class T> class local_shared_ptr +{ +private: + + typedef local_shared_ptr this_type; + +public: + + typedef typename boost::detail::sp_element<T>::type element_type; + +private: + + element_type * px; + boost::detail::local_counted_base * pn; + + template<class Y> friend class local_shared_ptr; + +public: + + // destructor + + ~local_shared_ptr() BOOST_SP_NOEXCEPT + { + if( pn ) + { + pn->release(); + } + } + + // constructors + + BOOST_CONSTEXPR local_shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn( 0 ) + { + } + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + BOOST_CONSTEXPR local_shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn( 0 ) + { + } + +#endif + + // internal constructor, used by make_shared + BOOST_CONSTEXPR local_shared_ptr( boost::detail::lsp_internal_constructor_tag, element_type * px_, boost::detail::local_counted_base * pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ ) + { + } + + template<class Y> + explicit local_shared_ptr( Y * p ): px( p ), pn( 0 ) + { + boost::detail::lsp_pointer_construct( this, p, pn ); + } + + template<class Y, class D> local_shared_ptr( Y * p, D d ): px( p ), pn( 0 ) + { + boost::detail::lsp_deleter_construct( this, p, d, pn ); + } + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + template<class D> local_shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( 0 ) + { + boost::detail::lsp_deleter_construct( this, p, d, pn ); + } + +#endif + + template<class Y, class D, class A> local_shared_ptr( Y * p, D d, A a ): px( p ), pn( 0 ) + { + boost::detail::lsp_allocator_construct( this, p, d, a, pn ); + } + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + template<class D, class A> local_shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( 0 ) + { + boost::detail::lsp_allocator_construct( this, p, d, a, pn ); + } + +#endif + + // construction from shared_ptr + + template<class Y> local_shared_ptr( shared_ptr<Y> const & r, + typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() ) + : px( r.get() ), pn( 0 ) + { + boost::detail::sp_assert_convertible< Y, T >(); + + if( r.use_count() != 0 ) + { + pn = new boost::detail::local_counted_impl( r._internal_count() ); + } + } + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + template<class Y> local_shared_ptr( shared_ptr<Y> && r, + typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() ) + : px( r.get() ), pn( 0 ) + { + boost::detail::sp_assert_convertible< Y, T >(); + + if( r.use_count() != 0 ) + { + pn = new boost::detail::local_counted_impl( r._internal_count() ); + r.reset(); + } + } + +#endif + + // construction from unique_ptr + +#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + template< class Y, class D > + local_shared_ptr( std::unique_ptr< Y, D > && r, + typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() ) + : px( r.get() ), pn( 0 ) + { + boost::detail::sp_assert_convertible< Y, T >(); + + if( px ) + { + pn = new boost::detail::local_counted_impl( shared_ptr<T>( std::move(r) )._internal_count() ); + } + } + +#endif + + template< class Y, class D > + local_shared_ptr( boost::movelib::unique_ptr< Y, D > r ); // ! + // : px( r.get() ), pn( new boost::detail::local_counted_impl( shared_ptr<T>( std::move(r) ) ) ) + //{ + // boost::detail::sp_assert_convertible< Y, T >(); + //} + + // copy constructor + + local_shared_ptr( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) + { + if( pn ) + { + pn->add_ref(); + } + } + + // move constructor + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + local_shared_ptr( local_shared_ptr && r ) BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) + { + r.px = 0; + r.pn = 0; + } + +#endif + + // converting copy constructor + + template<class Y> local_shared_ptr( local_shared_ptr<Y> const & r, + typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() ) BOOST_SP_NOEXCEPT + : px( r.px ), pn( r.pn ) + { + boost::detail::sp_assert_convertible< Y, T >(); + + if( pn ) + { + pn->add_ref(); + } + } + + // converting move constructor + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + template<class Y> local_shared_ptr( local_shared_ptr<Y> && r, + typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty() ) BOOST_SP_NOEXCEPT + : px( r.px ), pn( r.pn ) + { + boost::detail::sp_assert_convertible< Y, T >(); + + r.px = 0; + r.pn = 0; + } + +#endif + + // aliasing + + template<class Y> + local_shared_ptr( local_shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn ) + { + if( pn ) + { + pn->add_ref(); + } + } + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + template<class Y> + local_shared_ptr( local_shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn ) + { + r.px = 0; + r.pn = 0; + } + +#endif + + // assignment + + local_shared_ptr & operator=( local_shared_ptr const & r ) BOOST_SP_NOEXCEPT + { + local_shared_ptr( r ).swap( *this ); + return *this; + } + + template<class Y> local_shared_ptr & operator=( local_shared_ptr<Y> const & r ) BOOST_SP_NOEXCEPT + { + local_shared_ptr( r ).swap( *this ); + return *this; + } + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + local_shared_ptr & operator=( local_shared_ptr && r ) BOOST_SP_NOEXCEPT + { + local_shared_ptr( std::move( r ) ).swap( *this ); + return *this; + } + + template<class Y> + local_shared_ptr & operator=( local_shared_ptr<Y> && r ) BOOST_SP_NOEXCEPT + { + local_shared_ptr( std::move( r ) ).swap( *this ); + return *this; + } + +#endif + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + + local_shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT + { + local_shared_ptr().swap(*this); + return *this; + } + +#endif + +#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + template<class Y, class D> + local_shared_ptr & operator=( std::unique_ptr<Y, D> && r ) + { + local_shared_ptr( std::move(r) ).swap( *this ); + return *this; + } + +#endif + + template<class Y, class D> + local_shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r ); // ! + + // reset + + void reset() BOOST_SP_NOEXCEPT + { + local_shared_ptr().swap( *this ); + } + + template<class Y> void reset( Y * p ) // Y must be complete + { + local_shared_ptr( p ).swap( *this ); + } + + template<class Y, class D> void reset( Y * p, D d ) + { + local_shared_ptr( p, d ).swap( *this ); + } + + template<class Y, class D, class A> void reset( Y * p, D d, A a ) + { + local_shared_ptr( p, d, a ).swap( *this ); + } + + template<class Y> void reset( local_shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT + { + local_shared_ptr( r, p ).swap( *this ); + } + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + template<class Y> void reset( local_shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT + { + local_shared_ptr( std::move( r ), p ).swap( *this ); + } + +#endif + + // accessors + + typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT + { + return *px; + } + + typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT + { + return px; + } + + typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT + { + BOOST_ASSERT( px != 0 ); + BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) ); + + return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] ); + } + + element_type * get() const BOOST_SP_NOEXCEPT + { + return px; + } + + // implicit conversion to "bool" +#include <boost/smart_ptr/detail/operator_bool.hpp> + + long local_use_count() const BOOST_SP_NOEXCEPT + { + return pn? pn->local_use_count(): 0; + } + + // conversions to shared_ptr, weak_ptr + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + template<class Y, class E = typename boost::detail::sp_enable_if_convertible<T,Y>::type> operator shared_ptr<Y>() const BOOST_SP_NOEXCEPT +#else + template<class Y> operator shared_ptr<Y>() const BOOST_SP_NOEXCEPT +#endif + { + boost::detail::sp_assert_convertible<T, Y>(); + + if( pn ) + { + return shared_ptr<Y>( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() ); + } + else + { + return shared_ptr<Y>(); + } + } + +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) && !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) + template<class Y, class E = typename boost::detail::sp_enable_if_convertible<T,Y>::type> operator weak_ptr<Y>() const BOOST_SP_NOEXCEPT +#else + template<class Y> operator weak_ptr<Y>() const BOOST_SP_NOEXCEPT +#endif + { + boost::detail::sp_assert_convertible<T, Y>(); + + if( pn ) + { + return shared_ptr<Y>( boost::detail::sp_internal_constructor_tag(), px, pn->local_cb_get_shared_count() ); + } + else + { + return weak_ptr<Y>(); + } + } + + // swap + + void swap( local_shared_ptr & r ) BOOST_SP_NOEXCEPT + { + std::swap( px, r.px ); + std::swap( pn, r.pn ); + } + + // owner_before + + template<class Y> bool owner_before( local_shared_ptr<Y> const & r ) const BOOST_SP_NOEXCEPT + { + return std::less< boost::detail::local_counted_base* >()( pn, r.pn ); + } +}; + +template<class T, class U> inline bool operator==( local_shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT +{ + return a.get() == b.get(); +} + +template<class T, class U> inline bool operator!=( local_shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT +{ + return a.get() != b.get(); +} + +#if !defined( BOOST_NO_CXX11_NULLPTR ) + +template<class T> inline bool operator==( local_shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT +{ + return p.get() == 0; +} + +template<class T> inline bool operator==( boost::detail::sp_nullptr_t, local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT +{ + return p.get() == 0; +} + +template<class T> inline bool operator!=( local_shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT +{ + return p.get() != 0; +} + +template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT +{ + return p.get() != 0; +} + +#endif + +template<class T, class U> inline bool operator==( local_shared_ptr<T> const & a, shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT +{ + return a.get() == b.get(); +} + +template<class T, class U> inline bool operator!=( local_shared_ptr<T> const & a, shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT +{ + return a.get() != b.get(); +} + +template<class T, class U> inline bool operator==( shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT +{ + return a.get() == b.get(); +} + +template<class T, class U> inline bool operator!=( shared_ptr<T> const & a, local_shared_ptr<U> const & b ) BOOST_SP_NOEXCEPT +{ + return a.get() != b.get(); +} + +template<class T, class U> inline bool operator<(local_shared_ptr<T> const & a, local_shared_ptr<U> const & b) BOOST_SP_NOEXCEPT +{ + return a.owner_before( b ); +} + +template<class T> inline void swap( local_shared_ptr<T> & a, local_shared_ptr<T> & b ) BOOST_SP_NOEXCEPT +{ + a.swap( b ); +} + +template<class T, class U> local_shared_ptr<T> static_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT +{ + (void) static_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename local_shared_ptr<T>::element_type E; + + E * p = static_cast< E* >( r.get() ); + return local_shared_ptr<T>( r, p ); +} + +template<class T, class U> local_shared_ptr<T> const_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT +{ + (void) const_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename local_shared_ptr<T>::element_type E; + + E * p = const_cast< E* >( r.get() ); + return local_shared_ptr<T>( r, p ); +} + +template<class T, class U> local_shared_ptr<T> dynamic_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT +{ + (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename local_shared_ptr<T>::element_type E; + + E * p = dynamic_cast< E* >( r.get() ); + return p? local_shared_ptr<T>( r, p ): local_shared_ptr<T>(); +} + +template<class T, class U> local_shared_ptr<T> reinterpret_pointer_cast( local_shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT +{ + (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename local_shared_ptr<T>::element_type E; + + E * p = reinterpret_cast< E* >( r.get() ); + return local_shared_ptr<T>( r, p ); +} + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + +template<class T, class U> local_shared_ptr<T> static_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT +{ + (void) static_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename local_shared_ptr<T>::element_type E; + + E * p = static_cast< E* >( r.get() ); + return local_shared_ptr<T>( std::move(r), p ); +} + +template<class T, class U> local_shared_ptr<T> const_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT +{ + (void) const_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename local_shared_ptr<T>::element_type E; + + E * p = const_cast< E* >( r.get() ); + return local_shared_ptr<T>( std::move(r), p ); +} + +template<class T, class U> local_shared_ptr<T> dynamic_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT +{ + (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename local_shared_ptr<T>::element_type E; + + E * p = dynamic_cast< E* >( r.get() ); + return p? local_shared_ptr<T>( std::move(r), p ): local_shared_ptr<T>(); +} + +template<class T, class U> local_shared_ptr<T> reinterpret_pointer_cast( local_shared_ptr<U> && r ) BOOST_SP_NOEXCEPT +{ + (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); + + typedef typename local_shared_ptr<T>::element_type E; + + E * p = reinterpret_cast< E* >( r.get() ); + return local_shared_ptr<T>( std::move(r), p ); +} + +#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + +// get_pointer() enables boost::mem_fn to recognize local_shared_ptr + +template<class T> inline typename local_shared_ptr<T>::element_type * get_pointer( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT +{ + return p.get(); +} + +// operator<< + +#if !defined(BOOST_NO_IOSTREAM) + +template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< ( std::basic_ostream<E, T> & os, local_shared_ptr<Y> const & p ) +{ + os << p.get(); + return os; +} + +#endif // !defined(BOOST_NO_IOSTREAM) + +// get_deleter + +template<class D, class T> D * get_deleter( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT +{ + return get_deleter<D>( shared_ptr<T>( p ) ); +} + +// hash_value + +template< class T > struct hash; + +template< class T > std::size_t hash_value( local_shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT +{ + return boost::hash< typename local_shared_ptr<T>::element_type* >()( p.get() ); +} + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED diff --git a/boost/smart_ptr/make_local_shared.hpp b/boost/smart_ptr/make_local_shared.hpp new file mode 100644 index 0000000000..23114fea26 --- /dev/null +++ b/boost/smart_ptr/make_local_shared.hpp @@ -0,0 +1,17 @@ +#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED +#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED + +// make_local_shared.hpp +// +// Copyright 2017 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://www.boost.org/libs/smart_ptr/ for documentation. + +#include <boost/smart_ptr/make_local_shared_object.hpp> +#include <boost/smart_ptr/make_local_shared_array.hpp> + +#endif // #ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_HPP_INCLUDED diff --git a/boost/smart_ptr/make_local_shared_array.hpp b/boost/smart_ptr/make_local_shared_array.hpp new file mode 100644 index 0000000000..663f83479b --- /dev/null +++ b/boost/smart_ptr/make_local_shared_array.hpp @@ -0,0 +1,67 @@ +/* +Copyright 2017 Peter Dimov +Copyright 2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP +#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP + +#include <boost/smart_ptr/allocate_local_shared_array.hpp> + +namespace boost { + +template<class T> +inline typename detail::lsp_if_size_array<T>::type +make_local_shared() +{ + return boost::allocate_local_shared<T>(std::allocator<typename + detail::sp_array_scalar<T>::type>()); +} + +template<class T> +inline typename detail::lsp_if_size_array<T>::type +make_local_shared(const typename detail::sp_array_element<T>::type& value) +{ + return boost::allocate_local_shared<T>(std::allocator<typename + detail::sp_array_scalar<T>::type>(), value); +} + +template<class T> +inline typename detail::lsp_if_array<T>::type +make_local_shared(std::size_t size) +{ + return boost::allocate_local_shared<T>(std::allocator<typename + detail::sp_array_scalar<T>::type>(), size); +} + +template<class T> +inline typename detail::lsp_if_array<T>::type +make_local_shared(std::size_t size, + const typename detail::sp_array_element<T>::type& value) +{ + return boost::allocate_local_shared<T>(std::allocator<typename + detail::sp_array_scalar<T>::type>(), size, value); +} + +template<class T> +inline typename detail::lsp_if_size_array<T>::type +make_local_shared_noinit() +{ + return allocate_local_shared_noinit<T>(std::allocator<typename + detail::sp_array_scalar<T>::type>()); +} + +template<class T> +inline typename detail::lsp_if_array<T>::type +make_local_shared_noinit(std::size_t size) +{ + return allocate_local_shared_noinit<T>(std::allocator<typename + detail::sp_array_scalar<T>::type>(), size); +} + +} /* boost */ + +#endif diff --git a/boost/smart_ptr/make_local_shared_object.hpp b/boost/smart_ptr/make_local_shared_object.hpp new file mode 100644 index 0000000000..ab83d60e61 --- /dev/null +++ b/boost/smart_ptr/make_local_shared_object.hpp @@ -0,0 +1,199 @@ +#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED +#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_OBJECT_HPP_INCLUDED + +// make_local_shared_object.hpp +// +// Copyright 2017 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// +// See http://www.boost.org/libs/smart_ptr/ for documentation. + +#include <boost/smart_ptr/local_shared_ptr.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/config.hpp> +#include <utility> +#include <cstddef> + +namespace boost +{ + +namespace detail +{ + +// lsp_if_not_array + +template<class T> struct lsp_if_not_array +{ + typedef boost::local_shared_ptr<T> type; +}; + +template<class T> struct lsp_if_not_array<T[]> +{ +}; + +template<class T, std::size_t N> struct lsp_if_not_array<T[N]> +{ +}; + +// lsp_ms_deleter + +template<class T, class A> class lsp_ms_deleter: public local_counted_impl_em +{ +private: + + typedef typename sp_aligned_storage<sizeof(T), ::boost::alignment_of<T>::value>::type storage_type; + + storage_type storage_; + A a_; + bool initialized_; + +private: + + void destroy() BOOST_SP_NOEXCEPT + { + if( initialized_ ) + { + T * p = reinterpret_cast< T* >( storage_.data_ ); + +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + std::allocator_traits<A>::destroy( a_, p ); + +#else + + p->~T(); + +#endif + + initialized_ = false; + } + } + +public: + + explicit lsp_ms_deleter( A const & a ) BOOST_SP_NOEXCEPT : a_( a ), initialized_( false ) + { + } + + // optimization: do not copy storage_ + lsp_ms_deleter( lsp_ms_deleter const & r ) BOOST_SP_NOEXCEPT : a_( r.a_), initialized_( false ) + { + } + + ~lsp_ms_deleter() BOOST_SP_NOEXCEPT + { + destroy(); + } + + void operator()( T * ) BOOST_SP_NOEXCEPT + { + destroy(); + } + + static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static + { + } + + void * address() BOOST_SP_NOEXCEPT + { + return storage_.data_; + } + + void set_initialized() BOOST_SP_NOEXCEPT + { + initialized_ = true; + } +}; + +} // namespace detail + +template<class T, class A, class... Args> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared( A const & a, Args&&... args ) +{ +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2; + +#else + + typedef typename A::template rebind<T>::other A2; + +#endif + + A2 a2( a ); + + typedef boost::detail::lsp_ms_deleter<T, A2> D; + + boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 ); + + D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() ); + void * pv = pd->address(); + +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + std::allocator_traits<A2>::construct( a2, static_cast< T* >( pv ), std::forward<Args>( args )... ); + +#else + + ::new( pv ) T( std::forward<Args>( args )... ); + +#endif + + pd->set_initialized(); + + T * pt2 = static_cast< T* >( pv ); + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + + pd->pn_ = pt._internal_count(); + + return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd ); +} + +template<class T, class A> typename boost::detail::lsp_if_not_array<T>::type allocate_local_shared_noinit( A const & a ) +{ +#if !defined( BOOST_NO_CXX11_ALLOCATOR ) + + typedef typename std::allocator_traits<A>::template rebind_alloc<T> A2; + +#else + + typedef typename A::template rebind<T>::other A2; + +#endif + + A2 a2( a ); + + typedef boost::detail::lsp_ms_deleter< T, std::allocator<T> > D; + + boost::shared_ptr<T> pt( static_cast< T* >( 0 ), boost::detail::sp_inplace_tag<D>(), a2 ); + + D * pd = static_cast< D* >( pt._internal_get_untyped_deleter() ); + void * pv = pd->address(); + + ::new( pv ) T; + + pd->set_initialized(); + + T * pt2 = static_cast< T* >( pv ); + boost::detail::sp_enable_shared_from_this( &pt, pt2, pt2 ); + + pd->pn_ = pt._internal_count(); + + return boost::local_shared_ptr<T>( boost::detail::lsp_internal_constructor_tag(), pt2, pd ); +} + +template<class T, class... Args> typename boost::detail::lsp_if_not_array<T>::type make_local_shared( Args&&... args ) +{ + return boost::allocate_local_shared<T>( std::allocator<T>(), std::forward<Args>(args)... ); +} + +template<class T> typename boost::detail::lsp_if_not_array<T>::type make_local_shared_noinit() +{ + return boost::allocate_shared_noinit<T>( std::allocator<T>() ); +} + +} // namespace boost + +#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED diff --git a/boost/smart_ptr/make_shared.hpp b/boost/smart_ptr/make_shared.hpp index 8d0e3ea400..dd9191c61d 100644 --- a/boost/smart_ptr/make_shared.hpp +++ b/boost/smart_ptr/make_shared.hpp @@ -9,8 +9,7 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt // -// See http://www.boost.org/libs/smart_ptr/make_shared.html -// for documentation. +// See http://www.boost.org/libs/smart_ptr/ for documentation. #include <boost/smart_ptr/make_shared_object.hpp> diff --git a/boost/smart_ptr/make_shared_object.hpp b/boost/smart_ptr/make_shared_object.hpp index 3bc78ee9ae..c681602dca 100644 --- a/boost/smart_ptr/make_shared_object.hpp +++ b/boost/smart_ptr/make_shared_object.hpp @@ -9,14 +9,14 @@ // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt // -// See http://www.boost.org/libs/smart_ptr/make_shared.html -// for documentation. +// See http://www.boost.org/libs/smart_ptr/ for documentation. #include <boost/config.hpp> #include <boost/move/core.hpp> #include <boost/move/utility_core.hpp> #include <boost/smart_ptr/shared_ptr.hpp> #include <boost/smart_ptr/detail/sp_forward.hpp> +#include <boost/smart_ptr/detail/sp_noexcept.hpp> #include <boost/type_traits/type_with_alignment.hpp> #include <boost/type_traits/alignment_of.hpp> #include <cstddef> @@ -48,7 +48,7 @@ private: private: - void destroy() + void destroy() BOOST_SP_NOEXCEPT { if( initialized_ ) { @@ -70,39 +70,39 @@ private: public: - sp_ms_deleter() BOOST_NOEXCEPT : initialized_( false ) + sp_ms_deleter() BOOST_SP_NOEXCEPT : initialized_( false ) { } - template<class A> explicit sp_ms_deleter( A const & ) BOOST_NOEXCEPT : initialized_( false ) + template<class A> explicit sp_ms_deleter( A const & ) BOOST_SP_NOEXCEPT : initialized_( false ) { } // optimization: do not copy storage_ - sp_ms_deleter( sp_ms_deleter const & ) BOOST_NOEXCEPT : initialized_( false ) + sp_ms_deleter( sp_ms_deleter const & ) BOOST_SP_NOEXCEPT : initialized_( false ) { } - ~sp_ms_deleter() + ~sp_ms_deleter() BOOST_SP_NOEXCEPT { destroy(); } - void operator()( T * ) + void operator()( T * ) BOOST_SP_NOEXCEPT { destroy(); } - static void operator_fn( T* ) // operator() can't be static + static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static { } - void * address() BOOST_NOEXCEPT + void * address() BOOST_SP_NOEXCEPT { return storage_.data_; } - void set_initialized() BOOST_NOEXCEPT + void set_initialized() BOOST_SP_NOEXCEPT { initialized_ = true; } @@ -120,7 +120,7 @@ private: private: - void destroy() + void destroy() BOOST_SP_NOEXCEPT { if( initialized_ ) { @@ -142,35 +142,35 @@ private: public: - sp_as_deleter( A const & a ) BOOST_NOEXCEPT : a_( a ), initialized_( false ) + sp_as_deleter( A const & a ) BOOST_SP_NOEXCEPT : a_( a ), initialized_( false ) { } // optimization: do not copy storage_ - sp_as_deleter( sp_as_deleter const & r ) BOOST_NOEXCEPT : a_( r.a_), initialized_( false ) + sp_as_deleter( sp_as_deleter const & r ) BOOST_SP_NOEXCEPT : a_( r.a_), initialized_( false ) { } - ~sp_as_deleter() + ~sp_as_deleter() BOOST_SP_NOEXCEPT { destroy(); } - void operator()( T * ) + void operator()( T * ) BOOST_SP_NOEXCEPT { destroy(); } - static void operator_fn( T* ) // operator() can't be static + static void operator_fn( T* ) BOOST_SP_NOEXCEPT // operator() can't be static { } - void * address() BOOST_NOEXCEPT + void * address() BOOST_SP_NOEXCEPT { return storage_.data_; } - void set_initialized() BOOST_NOEXCEPT + void set_initialized() BOOST_SP_NOEXCEPT { initialized_ = true; } diff --git a/boost/smart_ptr/owner_less.hpp b/boost/smart_ptr/owner_less.hpp index 75d182c121..5f50aeb5b8 100644 --- a/boost/smart_ptr/owner_less.hpp +++ b/boost/smart_ptr/owner_less.hpp @@ -11,7 +11,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // -// See http://www.boost.org/libs/smart_ptr/smart_ptr.htm for documentation. +// See http://www.boost.org/libs/smart_ptr/ for documentation. // namespace boost diff --git a/boost/smart_ptr/scoped_array.hpp b/boost/smart_ptr/scoped_array.hpp index f847c094e4..05dd05aea8 100644 --- a/boost/smart_ptr/scoped_array.hpp +++ b/boost/smart_ptr/scoped_array.hpp @@ -8,8 +8,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // -// http://www.boost.org/libs/smart_ptr/scoped_array.htm -// +// See http://www.boost.org/libs/smart_ptr/ for documentation. #include <boost/config.hpp> #include <boost/assert.hpp> @@ -62,7 +61,7 @@ public: #endif } - ~scoped_array() // never throws + ~scoped_array() BOOST_SP_NOEXCEPT { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_array_destructor_hook( px ); @@ -70,20 +69,20 @@ public: boost::checked_array_delete( px ); } - void reset(T * p = 0) // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) + void reset(T * p = 0) BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors this_type(p).swap(*this); } - T & operator[](std::ptrdiff_t i) const // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) + T & operator[](std::ptrdiff_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( px != 0 ); BOOST_ASSERT( i >= 0 ); return px[i]; } - T * get() const BOOST_NOEXCEPT + T * get() const BOOST_SP_NOEXCEPT { return px; } @@ -91,7 +90,7 @@ public: // implicit conversion to "bool" #include <boost/smart_ptr/detail/operator_bool.hpp> - void swap(scoped_array & b) BOOST_NOEXCEPT + void swap(scoped_array & b) BOOST_SP_NOEXCEPT { T * tmp = b.px; b.px = px; @@ -101,29 +100,29 @@ public: #if !defined( BOOST_NO_CXX11_NULLPTR ) -template<class T> inline bool operator==( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +template<class T> inline bool operator==( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() == 0; } -template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_NOEXCEPT +template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_SP_NOEXCEPT { return p.get() == 0; } -template<class T> inline bool operator!=( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +template<class T> inline bool operator!=( scoped_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() != 0; } -template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_NOEXCEPT +template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_array<T> const & p ) BOOST_SP_NOEXCEPT { return p.get() != 0; } #endif -template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) BOOST_NOEXCEPT +template<class T> inline void swap(scoped_array<T> & a, scoped_array<T> & b) BOOST_SP_NOEXCEPT { a.swap(b); } diff --git a/boost/smart_ptr/scoped_ptr.hpp b/boost/smart_ptr/scoped_ptr.hpp index 8fd8a180fb..5325eba5ff 100644 --- a/boost/smart_ptr/scoped_ptr.hpp +++ b/boost/smart_ptr/scoped_ptr.hpp @@ -8,8 +8,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // -// http://www.boost.org/libs/smart_ptr/scoped_ptr.htm -// +// See http://www.boost.org/libs/smart_ptr/ for documentation. #include <boost/config.hpp> #include <boost/assert.hpp> @@ -63,7 +62,7 @@ public: typedef T element_type; - explicit scoped_ptr( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p ) // never throws + explicit scoped_ptr( T * p = 0 ) BOOST_SP_NOEXCEPT : px( p ) { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_constructor_hook( px ); @@ -72,7 +71,7 @@ public: #ifndef BOOST_NO_AUTO_PTR - explicit scoped_ptr( std::auto_ptr<T> p ) BOOST_NOEXCEPT : px( p.release() ) + explicit scoped_ptr( std::auto_ptr<T> p ) BOOST_SP_NOEXCEPT : px( p.release() ) { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_constructor_hook( px ); @@ -81,7 +80,7 @@ public: #endif - ~scoped_ptr() // never throws + ~scoped_ptr() BOOST_SP_NOEXCEPT { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_destructor_hook( px ); @@ -89,25 +88,25 @@ public: boost::checked_delete( px ); } - void reset(T * p = 0) // never throws + void reset(T * p = 0) BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors this_type(p).swap(*this); } - T & operator*() const // never throws + T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( px != 0 ); return *px; } - T * operator->() const // never throws + T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( px != 0 ); return px; } - T * get() const BOOST_NOEXCEPT + T * get() const BOOST_SP_NOEXCEPT { return px; } @@ -115,7 +114,7 @@ public: // implicit conversion to "bool" #include <boost/smart_ptr/detail/operator_bool.hpp> - void swap(scoped_ptr & b) BOOST_NOEXCEPT + void swap(scoped_ptr & b) BOOST_SP_NOEXCEPT { T * tmp = b.px; b.px = px; @@ -125,36 +124,36 @@ public: #if !defined( BOOST_NO_CXX11_NULLPTR ) -template<class T> inline bool operator==( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +template<class T> inline bool operator==( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() == 0; } -template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_NOEXCEPT +template<class T> inline bool operator==( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_SP_NOEXCEPT { return p.get() == 0; } -template<class T> inline bool operator!=( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +template<class T> inline bool operator!=( scoped_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() != 0; } -template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_NOEXCEPT +template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, scoped_ptr<T> const & p ) BOOST_SP_NOEXCEPT { return p.get() != 0; } #endif -template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) BOOST_NOEXCEPT +template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) BOOST_SP_NOEXCEPT { a.swap(b); } // get_pointer(p) is a generic way to say p.get() -template<class T> inline T * get_pointer(scoped_ptr<T> const & p) BOOST_NOEXCEPT +template<class T> inline T * get_pointer(scoped_ptr<T> const & p) BOOST_SP_NOEXCEPT { return p.get(); } diff --git a/boost/smart_ptr/shared_array.hpp b/boost/smart_ptr/shared_array.hpp index 2e5cb134a3..3ffa7426c3 100644 --- a/boost/smart_ptr/shared_array.hpp +++ b/boost/smart_ptr/shared_array.hpp @@ -11,7 +11,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // -// See http://www.boost.org/libs/smart_ptr/shared_array.htm for documentation. +// See http://www.boost.org/libs/smart_ptr/ for documentation. // #include <boost/config.hpp> // for broken compiler workarounds @@ -120,7 +120,7 @@ public: shared_array( shared_array<Y> const & r ) #endif - BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) // never throws + BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) { boost::detail::sp_assert_convertible< Y[], T[] >(); } @@ -128,7 +128,7 @@ public: // aliasing template< class Y > - shared_array( shared_array<Y> const & r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn( r.pn ) + shared_array( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn ) { } @@ -143,7 +143,7 @@ public: #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400) template<class Y> - shared_array & operator=( shared_array<Y> const & r ) BOOST_NOEXCEPT + shared_array & operator=( shared_array<Y> const & r ) BOOST_SP_NOEXCEPT { this_type( r ).swap( *this ); return *this; @@ -160,7 +160,7 @@ public: } template<class Y> - shared_array & operator=( shared_array<Y> && r ) BOOST_NOEXCEPT + shared_array & operator=( shared_array<Y> && r ) BOOST_SP_NOEXCEPT { this_type( static_cast< shared_array<Y> && >( r ) ).swap( *this ); return *this; @@ -168,7 +168,7 @@ public: #endif - void reset() BOOST_NOEXCEPT + void reset() BOOST_SP_NOEXCEPT { this_type().swap( *this ); } @@ -189,19 +189,19 @@ public: this_type( p, d, a ).swap( *this ); } - template<class Y> void reset( shared_array<Y> const & r, element_type * p ) + template<class Y> void reset( shared_array<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT { this_type( r, p ).swap( *this ); } - T & operator[] (std::ptrdiff_t i) const // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) + T & operator[] (std::ptrdiff_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT(px != 0); BOOST_ASSERT(i >= 0); return px[i]; } - T * get() const BOOST_NOEXCEPT + T * get() const BOOST_SP_NOEXCEPT { return px; } @@ -209,23 +209,23 @@ public: // implicit conversion to "bool" #include <boost/smart_ptr/detail/operator_bool.hpp> - bool unique() const BOOST_NOEXCEPT + bool unique() const BOOST_SP_NOEXCEPT { return pn.unique(); } - long use_count() const BOOST_NOEXCEPT + long use_count() const BOOST_SP_NOEXCEPT { return pn.use_count(); } - void swap(shared_array<T> & other) BOOST_NOEXCEPT + void swap(shared_array<T> & other) BOOST_SP_NOEXCEPT { std::swap(px, other.px); pn.swap(other.pn); } - void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const + void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT { return pn.get_deleter( ti ); } @@ -239,51 +239,51 @@ private: }; // shared_array -template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) BOOST_NOEXCEPT +template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT { return a.get() == b.get(); } -template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) BOOST_NOEXCEPT +template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT { return a.get() != b.get(); } #if !defined( BOOST_NO_CXX11_NULLPTR ) -template<class T> inline bool operator==( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +template<class T> inline bool operator==( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() == 0; } -template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_NOEXCEPT +template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT { return p.get() == 0; } -template<class T> inline bool operator!=( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +template<class T> inline bool operator!=( shared_array<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() != 0; } -template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_NOEXCEPT +template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_array<T> const & p ) BOOST_SP_NOEXCEPT { return p.get() != 0; } #endif -template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) BOOST_NOEXCEPT +template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) BOOST_SP_NOEXCEPT { return std::less<T*>()(a.get(), b.get()); } -template<class T> void swap(shared_array<T> & a, shared_array<T> & b) BOOST_NOEXCEPT +template<class T> void swap(shared_array<T> & a, shared_array<T> & b) BOOST_SP_NOEXCEPT { a.swap(b); } -template< class D, class T > D * get_deleter( shared_array<T> const & p ) +template< class D, class T > D * get_deleter( shared_array<T> const & p ) BOOST_SP_NOEXCEPT { return static_cast< D * >( p._internal_get_deleter( BOOST_SP_TYPEID(D) ) ); } diff --git a/boost/smart_ptr/shared_ptr.hpp b/boost/smart_ptr/shared_ptr.hpp index e33707b3bc..e8a302c74a 100644 --- a/boost/smart_ptr/shared_ptr.hpp +++ b/boost/smart_ptr/shared_ptr.hpp @@ -11,7 +11,7 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // -// See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation. +// See http://www.boost.org/libs/smart_ptr/ for documentation. // #include <boost/config.hpp> // for broken compiler workarounds @@ -262,7 +262,7 @@ template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R // sp_assert_convertible -template< class Y, class T > inline void sp_assert_convertible() +template< class Y, class T > inline void sp_assert_convertible() BOOST_SP_NOEXCEPT { #if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) @@ -323,6 +323,10 @@ template< class T, std::size_t N, class Y > inline void sp_deleter_construct( bo #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) +struct sp_internal_constructor_tag +{ +}; + } // namespace detail @@ -345,13 +349,25 @@ public: typedef typename boost::detail::sp_element< T >::type element_type; - shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn() // never throws in 1.30+ + BOOST_CONSTEXPR shared_ptr() BOOST_SP_NOEXCEPT : px( 0 ), pn() { } #if !defined( BOOST_NO_CXX11_NULLPTR ) - shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn() // never throws + BOOST_CONSTEXPR shared_ptr( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT : px( 0 ), pn() + { + } + +#endif + + BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count const & pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ ) + { + } + +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + BOOST_CONSTEXPR shared_ptr( boost::detail::sp_internal_constructor_tag, element_type * px_, boost::detail::shared_count && pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( std::move( pn_ ) ) { } @@ -420,7 +436,7 @@ public: template<class Y> shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag ) - BOOST_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) + BOOST_SP_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() ) { if( !pn.empty() ) { @@ -438,14 +454,14 @@ public: shared_ptr( shared_ptr<Y> const & r ) #endif - BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) + BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) { boost::detail::sp_assert_convertible< Y, T >(); } // aliasing template< class Y > - shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn( r.pn ) + shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn( r.pn ) { } @@ -502,9 +518,12 @@ public: boost::detail::sp_assert_convertible< Y, T >(); typename std::unique_ptr< Y, D >::pointer tmp = r.get(); - pn = boost::detail::shared_count( r ); - boost::detail::sp_deleter_construct( this, tmp ); + if( tmp != 0 ) + { + pn = boost::detail::shared_count( r ); + boost::detail::sp_deleter_construct( this, tmp ); + } } #endif @@ -515,9 +534,12 @@ public: boost::detail::sp_assert_convertible< Y, T >(); typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get(); - pn = boost::detail::shared_count( r ); - boost::detail::sp_deleter_construct( this, tmp ); + if( tmp != 0 ) + { + pn = boost::detail::shared_count( r ); + boost::detail::sp_deleter_construct( this, tmp ); + } } // assignment @@ -531,7 +553,7 @@ public: #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400) template<class Y> - shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_NOEXCEPT + shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_SP_NOEXCEPT { this_type(r).swap(*this); return *this; @@ -592,10 +614,13 @@ public: shared_ptr tmp; - tmp.px = p; - tmp.pn = boost::detail::shared_count( r ); + if( p != 0 ) + { + tmp.px = p; + tmp.pn = boost::detail::shared_count( r ); - boost::detail::sp_deleter_construct( &tmp, p ); + boost::detail::sp_deleter_construct( &tmp, p ); + } tmp.swap( *this ); @@ -622,7 +647,7 @@ public: shared_ptr( shared_ptr<Y> && r ) #endif - BOOST_NOEXCEPT : px( r.px ), pn() + BOOST_SP_NOEXCEPT : px( r.px ), pn() { boost::detail::sp_assert_convertible< Y, T >(); @@ -637,7 +662,7 @@ public: } template<class Y> - shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_NOEXCEPT + shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_SP_NOEXCEPT { this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this ); return *this; @@ -645,7 +670,7 @@ public: // aliasing move template<class Y> - shared_ptr( shared_ptr<Y> && r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn() + shared_ptr( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT : px( p ), pn() { pn.swap( r.pn ); r.px = 0; @@ -655,7 +680,7 @@ public: #if !defined( BOOST_NO_CXX11_NULLPTR ) - shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT // never throws + shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { this_type().swap(*this); return *this; @@ -663,7 +688,7 @@ public: #endif - void reset() BOOST_NOEXCEPT // never throws in 1.30+ + void reset() BOOST_SP_NOEXCEPT { this_type().swap(*this); } @@ -684,36 +709,33 @@ public: this_type( p, d, a ).swap( *this ); } - template<class Y> void reset( shared_ptr<Y> const & r, element_type * p ) + template<class Y> void reset( shared_ptr<Y> const & r, element_type * p ) BOOST_SP_NOEXCEPT { this_type( r, p ).swap( *this ); } #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) - template<class Y> void reset( shared_ptr<Y> && r, element_type * p ) + template<class Y> void reset( shared_ptr<Y> && r, element_type * p ) BOOST_SP_NOEXCEPT { this_type( static_cast< shared_ptr<Y> && >( r ), p ).swap( *this ); } #endif - // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) - typename boost::detail::sp_dereference< T >::type operator* () const + typename boost::detail::sp_dereference< T >::type operator* () const BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( px != 0 ); return *px; } - // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) - typename boost::detail::sp_member_access< T >::type operator-> () const + typename boost::detail::sp_member_access< T >::type operator-> () const BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( px != 0 ); return px; } - // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT) - typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const + typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( px != 0 ); BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) ); @@ -721,7 +743,7 @@ public: return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] ); } - element_type * get() const BOOST_NOEXCEPT + element_type * get() const BOOST_SP_NOEXCEPT { return px; } @@ -729,47 +751,57 @@ public: // implicit conversion to "bool" #include <boost/smart_ptr/detail/operator_bool.hpp> - bool unique() const BOOST_NOEXCEPT + bool unique() const BOOST_SP_NOEXCEPT { return pn.unique(); } - long use_count() const BOOST_NOEXCEPT + long use_count() const BOOST_SP_NOEXCEPT { return pn.use_count(); } - void swap( shared_ptr & other ) BOOST_NOEXCEPT + void swap( shared_ptr & other ) BOOST_SP_NOEXCEPT { std::swap(px, other.px); pn.swap(other.pn); } - template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT + template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT { return pn < rhs.pn; } - template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_NOEXCEPT + template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT { return pn < rhs.pn; } - void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_NOEXCEPT + void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT { return pn.get_deleter( ti ); } - void * _internal_get_untyped_deleter() const BOOST_NOEXCEPT + void * _internal_get_local_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_SP_NOEXCEPT + { + return pn.get_local_deleter( ti ); + } + + void * _internal_get_untyped_deleter() const BOOST_SP_NOEXCEPT { return pn.get_untyped_deleter(); } - bool _internal_equiv( shared_ptr const & r ) const BOOST_NOEXCEPT + bool _internal_equiv( shared_ptr const & r ) const BOOST_SP_NOEXCEPT { return px == r.px && pn == r.pn; } + boost::detail::shared_count _internal_count() const BOOST_NOEXCEPT + { + return pn; + } + // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. (Matthew Langston) @@ -788,12 +820,12 @@ private: }; // shared_ptr -template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT +template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT { return a.get() == b.get(); } -template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT +template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT { return a.get() != b.get(); } @@ -802,7 +834,7 @@ template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, share // Resolve the ambiguity between our op!= and the one in rel_ops -template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_NOEXCEPT +template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_SP_NOEXCEPT { return a.get() != b.get(); } @@ -811,39 +843,39 @@ template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> #if !defined( BOOST_NO_CXX11_NULLPTR ) -template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() == 0; } -template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT +template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT { return p.get() == 0; } -template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT +template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT { return p.get() != 0; } -template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT +template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT { return p.get() != 0; } #endif -template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT +template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_SP_NOEXCEPT { return a.owner_before( b ); } -template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT +template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_SP_NOEXCEPT { a.swap(b); } -template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT +template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT { (void) static_cast< T* >( static_cast< U* >( 0 ) ); @@ -853,7 +885,7 @@ template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> cons return shared_ptr<T>( r, p ); } -template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT +template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT { (void) const_cast< T* >( static_cast< U* >( 0 ) ); @@ -863,7 +895,7 @@ template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const return shared_ptr<T>( r, p ); } -template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT +template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT { (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); @@ -873,7 +905,7 @@ template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> con return p? shared_ptr<T>( r, p ): shared_ptr<T>(); } -template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT +template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_SP_NOEXCEPT { (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); @@ -885,7 +917,7 @@ template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) -template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) BOOST_NOEXCEPT +template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT { (void) static_cast< T* >( static_cast< U* >( 0 ) ); @@ -895,7 +927,7 @@ template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> && r return shared_ptr<T>( std::move(r), p ); } -template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r ) BOOST_NOEXCEPT +template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT { (void) const_cast< T* >( static_cast< U* >( 0 ) ); @@ -905,7 +937,7 @@ template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> && r return shared_ptr<T>( std::move(r), p ); } -template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && r ) BOOST_NOEXCEPT +template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT { (void) dynamic_cast< T* >( static_cast< U* >( 0 ) ); @@ -915,7 +947,7 @@ template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> && return p? shared_ptr<T>( std::move(r), p ): shared_ptr<T>(); } -template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> && r ) BOOST_NOEXCEPT +template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> && r ) BOOST_SP_NOEXCEPT { (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) ); @@ -929,7 +961,7 @@ template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> // get_pointer() enables boost::mem_fn to recognize shared_ptr -template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_NOEXCEPT +template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_SP_NOEXCEPT { return p.get(); } @@ -974,27 +1006,13 @@ template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std:: namespace detail { -#if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \ - ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \ - ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) ) - -// g++ 2.9x doesn't allow static_cast<X const *>(void *) -// apparently EDG 2.38 and HP aCC A.03.35 also don't accept it - -template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p) -{ - void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D)); - return const_cast<D *>(static_cast<D const *>(q)); -} - -#else - -template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT +template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT { return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID(D)) ); } -#endif +template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT; +template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT; class esft2_deleter_wrapper { @@ -1008,17 +1026,17 @@ public: { } - template< class T > void set_deleter( shared_ptr<T> const & deleter ) + template< class T > void set_deleter( shared_ptr<T> const & deleter ) BOOST_SP_NOEXCEPT { deleter_ = deleter; } - template<typename D> D* get_deleter() const BOOST_NOEXCEPT + template<typename D> D* get_deleter() const BOOST_SP_NOEXCEPT { return boost::detail::basic_get_deleter<D>( deleter_ ); } - template< class T> void operator()( T* ) + template< class T> void operator()( T* ) BOOST_SP_NOEXCEPT_WITH_ASSERT { BOOST_ASSERT( deleter_.use_count() <= 1 ); deleter_.reset(); @@ -1027,53 +1045,58 @@ public: } // namespace detail -template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT +template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT { - D *del = boost::detail::basic_get_deleter<D>(p); + D * d = boost::detail::basic_get_deleter<D>( p ); + + if( d == 0 ) + { + d = boost::detail::basic_get_local_deleter( d, p ); + } - if(del == 0) + if( d == 0 ) { boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p); // The following get_deleter method call is fully qualified because // older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>() - if(del_wrapper) del = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>(); + if(del_wrapper) d = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>(); } - return del; + return d; } // atomic access #if !defined(BOOST_SP_NO_ATOMIC_ACCESS) -template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_NOEXCEPT +template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_SP_NOEXCEPT { return false; } -template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) +template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p ) BOOST_SP_NOEXCEPT { boost::detail::spinlock_pool<2>::scoped_lock lock( p ); return *p; } -template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ int ) +template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ int ) BOOST_SP_NOEXCEPT { return atomic_load( p ); } -template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) +template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT { boost::detail::spinlock_pool<2>::scoped_lock lock( p ); p->swap( r ); } -template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int ) +template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int ) BOOST_SP_NOEXCEPT { atomic_store( p, r ); // std::move( r ) } -template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) +template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r ) BOOST_SP_NOEXCEPT { boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); @@ -1084,12 +1107,12 @@ template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T return r; // return std::move( r ) } -template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int ) +template<class T> shared_ptr<T> inline atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int ) BOOST_SP_NOEXCEPT { return atomic_exchange( p, r ); // std::move( r ) } -template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) +template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w ) BOOST_SP_NOEXCEPT { boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p ); @@ -1114,7 +1137,7 @@ template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> } } -template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ int, /*memory_order failure*/ int ) +template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ int, /*memory_order failure*/ int ) BOOST_SP_NOEXCEPT { return atomic_compare_exchange( p, v, w ); // std::move( w ) } @@ -1125,13 +1148,35 @@ template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * template< class T > struct hash; -template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_NOEXCEPT +template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT { return boost::hash< typename boost::shared_ptr<T>::element_type* >()( p.get() ); } } // namespace boost +#include <boost/smart_ptr/detail/local_sp_deleter.hpp> + +namespace boost +{ + +namespace detail +{ + +template<class D, class T> D * basic_get_local_deleter( D *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT +{ + return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID(local_sp_deleter<D>) ) ); +} + +template<class D, class T> D const * basic_get_local_deleter( D const *, shared_ptr<T> const & p ) BOOST_SP_NOEXCEPT +{ + return static_cast<D *>( p._internal_get_local_deleter( BOOST_SP_TYPEID(local_sp_deleter<D>) ) ); +} + +} // namespace detail + +} // namespace boost + #if defined( BOOST_SP_DISABLE_DEPRECATED ) #pragma GCC diagnostic pop #endif diff --git a/boost/smart_ptr/weak_ptr.hpp b/boost/smart_ptr/weak_ptr.hpp index f3411f7225..54d9ef3781 100644 --- a/boost/smart_ptr/weak_ptr.hpp +++ b/boost/smart_ptr/weak_ptr.hpp @@ -6,11 +6,11 @@ // // Copyright (c) 2001, 2002, 2003 Peter Dimov // -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) // -// See http://www.boost.org/libs/smart_ptr/weak_ptr.htm for documentation. +// See http://www.boost.org/libs/smart_ptr/ for documentation. // #include <memory> // boost.TR1 include order fix @@ -32,7 +32,7 @@ public: typedef typename boost::detail::sp_element< T >::type element_type; - weak_ptr() BOOST_SP_NOEXCEPT : px(0), pn() // never throws in 1.30+ + BOOST_CONSTEXPR weak_ptr() BOOST_SP_NOEXCEPT : px(0), pn() { } @@ -59,7 +59,7 @@ public: // The "obvious" converting constructor implementation: // // template<class Y> -// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws +// weak_ptr(weak_ptr<Y> const & r): px(r.px), pn(r.pn) // { // } // @@ -82,7 +82,7 @@ public: weak_ptr( weak_ptr<Y> const & r ) #endif - BOOST_NOEXCEPT : px(r.lock().get()), pn(r.pn) + BOOST_SP_NOEXCEPT : px(r.lock().get()), pn(r.pn) { boost::detail::sp_assert_convertible< Y, T >(); } @@ -99,7 +99,7 @@ public: weak_ptr( weak_ptr<Y> && r ) #endif - BOOST_NOEXCEPT : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) + BOOST_SP_NOEXCEPT : px( r.lock().get() ), pn( static_cast< boost::detail::weak_count && >( r.pn ) ) { boost::detail::sp_assert_convertible< Y, T >(); r.px = 0; @@ -132,7 +132,7 @@ public: weak_ptr( shared_ptr<Y> const & r ) #endif - BOOST_NOEXCEPT : px( r.px ), pn( r.pn ) + BOOST_SP_NOEXCEPT : px( r.px ), pn( r.pn ) { boost::detail::sp_assert_convertible< Y, T >(); } @@ -140,7 +140,7 @@ public: #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1300) template<class Y> - weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_NOEXCEPT + weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_SP_NOEXCEPT { boost::detail::sp_assert_convertible< Y, T >(); @@ -153,7 +153,7 @@ public: #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) template<class Y> - weak_ptr & operator=( weak_ptr<Y> && r ) BOOST_NOEXCEPT + weak_ptr & operator=( weak_ptr<Y> && r ) BOOST_SP_NOEXCEPT { this_type( static_cast< weak_ptr<Y> && >( r ) ).swap( *this ); return *this; @@ -162,7 +162,7 @@ public: #endif template<class Y> - weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_NOEXCEPT + weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_SP_NOEXCEPT { boost::detail::sp_assert_convertible< Y, T >(); @@ -174,50 +174,50 @@ public: #endif - shared_ptr<T> lock() const BOOST_NOEXCEPT + shared_ptr<T> lock() const BOOST_SP_NOEXCEPT { return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() ); } - long use_count() const BOOST_NOEXCEPT + long use_count() const BOOST_SP_NOEXCEPT { return pn.use_count(); } - bool expired() const BOOST_NOEXCEPT + bool expired() const BOOST_SP_NOEXCEPT { return pn.use_count() == 0; } - bool _empty() const // extension, not in std::weak_ptr + bool _empty() const BOOST_SP_NOEXCEPT // extension, not in std::weak_ptr { return pn.empty(); } - void reset() BOOST_NOEXCEPT // never throws in 1.30+ + void reset() BOOST_SP_NOEXCEPT { this_type().swap(*this); } - void swap(this_type & other) BOOST_NOEXCEPT + void swap(this_type & other) BOOST_SP_NOEXCEPT { std::swap(px, other.px); pn.swap(other.pn); } template<typename Y> - void _internal_aliasing_assign(weak_ptr<Y> const & r, element_type * px2) + 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_NOEXCEPT + template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT { return pn < rhs.pn; } - template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT + template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_SP_NOEXCEPT { return pn < rhs.pn; } @@ -239,12 +239,12 @@ private: }; // weak_ptr -template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) BOOST_NOEXCEPT +template<class T, class U> inline bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b) BOOST_SP_NOEXCEPT { return a.owner_before( b ); } -template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) BOOST_NOEXCEPT +template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b) BOOST_SP_NOEXCEPT { a.swap(b); } |