diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index a27b99f..bdd8b1f 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -9,152 +9,172 @@ #ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP -#include -#include +#include #include -#include namespace boost { - template + template inline typename boost::detail::sp_if_array::type allocate_shared(const A& allocator, std::size_t size) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; - typedef boost::detail::as_allocator A1; - typedef boost::detail::as_deleter D1; - T1* p1 = 0; - T3* p2 = 0; + typedef boost::detail::ms_init_tag R1; + typedef boost::detail::as_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; std::size_t n1 = size * boost::detail::array_total::size; - D1 d1(allocator, n1); - A1 a1(allocator, n1, &p2); - boost::shared_ptr s1(p1, d1, a1); - p1 = reinterpret_cast(p2); + T1* p1 = 0; + T2* p2 = 0; + D1 d1; + A1 a1(allocator, size, &p2); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); +#if !defined(BOOST_NO_CXX11_ALLOCATOR) boost::detail::as_init(allocator, p2, n1); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); +#else + boost::detail::ms_init(p2, n1); +#endif + a2->set(p2); + p1 = reinterpret_cast(p2); + return shared_ptr(s1, p1); } - template + template inline typename boost::detail::sp_if_size_array::type allocate_shared(const A& allocator) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; + typedef boost::detail::ms_init_tag R1; + typedef boost::detail::as_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; enum { N = boost::detail::array_total::size }; - typedef boost::detail::as_allocator A1; - typedef boost::detail::as_deleter D1; T1* p1 = 0; - T3* p2 = 0; - D1 d1(allocator); + T2* p2 = 0; + D1 d1; A1 a1(allocator, &p2); - boost::shared_ptr s1(p1, d1, a1); - p1 = reinterpret_cast(p2); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); +#if !defined(BOOST_NO_CXX11_ALLOCATOR) boost::detail::as_init(allocator, p2, N); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); +#else + boost::detail::ms_init(p2, N); +#endif + a2->set(p2); + p1 = reinterpret_cast(p2); + return shared_ptr(s1, p1); } - template + template inline typename boost::detail::sp_if_array::type allocate_shared(const A& allocator, std::size_t size, const typename boost::detail::array_inner::type& value) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; - typedef const T2 T4; - typedef boost::detail::as_allocator A1; - typedef boost::detail::as_deleter D1; + typedef const T2 T3; + typedef boost::detail::ms_init_tag R1; + typedef boost::detail::as_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; enum { M = boost::detail::array_total::size }; - T1* p1 = 0; - T3* p2 = 0; - T4* p3 = reinterpret_cast(&value); std::size_t n1 = M * size; - D1 d1(allocator, n1); - A1 a1(allocator, n1, &p2); - boost::shared_ptr s1(p1, d1, a1); + T1* p1 = 0; + T2* p2 = 0; + T3* p3 = reinterpret_cast(&value); + D1 d1; + A1 a1(allocator, size, &p2); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + boost::detail::as_init(allocator, p2, n1, p3); +#else + boost::detail::ms_init(p2, n1, p3); +#endif + a2->set(p2); p1 = reinterpret_cast(p2); - boost::detail::as_init(allocator, p2, n1, p3); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); + return shared_ptr(s1, p1); } - template + template inline typename boost::detail::sp_if_size_array::type allocate_shared(const A& allocator, const typename boost::detail::array_inner::type& value) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; - typedef const T2 T4; + typedef const T2 T3; + typedef boost::detail::ms_init_tag R1; + typedef boost::detail::as_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; enum { - M = boost::detail::array_total::size, - N = boost::detail::array_total::size + N = boost::detail::array_total::size, + M = boost::detail::array_total::size }; - typedef boost::detail::as_allocator A1; - typedef boost::detail::as_deleter D1; T1* p1 = 0; - T3* p2 = 0; - T4* p3 = reinterpret_cast(&value); - D1 d1(allocator); + T2* p2 = 0; + T3* p3 = reinterpret_cast(&value); + D1 d1; A1 a1(allocator, &p2); - boost::shared_ptr s1(p1, d1, a1); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + boost::detail::as_init(allocator, p2, N, p3); +#else + boost::detail::ms_init(p2, N, p3); +#endif + a2->set(p2); p1 = reinterpret_cast(p2); - boost::detail::as_init(allocator, p2, N, p3); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); + return shared_ptr(s1, p1); } - template + template inline typename boost::detail::sp_if_array::type allocate_shared_noinit(const A& allocator, std::size_t size) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; - typedef boost::detail::as_allocator A1; - typedef boost::detail::ms_deleter D1; - T1* p1 = 0; - T3* p2 = 0; + typedef boost::detail::ms_noinit_tag R1; + typedef boost::detail::as_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; std::size_t n1 = size * boost::detail::array_total::size; - D1 d1(n1); - A1 a1(allocator, n1, &p2); - boost::shared_ptr s1(p1, d1, a1); - p1 = reinterpret_cast(p2); + T1* p1 = 0; + T2* p2 = 0; + D1 d1; + A1 a1(allocator, size, &p2); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); boost::detail::ms_noinit(p2, n1); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); + a2->set(p2); + p1 = reinterpret_cast(p2); + return shared_ptr(s1, p1); } - template + template inline typename boost::detail::sp_if_size_array::type allocate_shared_noinit(const A& allocator) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; + typedef boost::detail::ms_noinit_tag R1; + typedef boost::detail::as_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; enum { N = boost::detail::array_total::size }; - typedef boost::detail::as_allocator A1; - typedef boost::detail::ms_deleter D1; T1* p1 = 0; - T3* p2 = 0; + T2* p2 = 0; D1 d1; A1 a1(allocator, &p2); - boost::shared_ptr s1(p1, d1, a1); - p1 = reinterpret_cast(p2); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); boost::detail::ms_noinit(p2, N); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); + a2->set(p2); + p1 = reinterpret_cast(p2); + return shared_ptr(s1, p1); } } diff --git a/include/boost/smart_ptr/detail/allocator_pair.hpp b/include/boost/smart_ptr/detail/allocator_pair.hpp deleted file mode 100644 index 8910c90..0000000 --- a/include/boost/smart_ptr/detail/allocator_pair.hpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2014 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#ifndef BOOST_SMART_PTR_DETAIL_ALLOCATOR_PAIR_HPP -#define BOOST_SMART_PTR_DETAIL_ALLOCATOR_PAIR_HPP - -#include - -namespace boost { - namespace detail { - template - struct as_pair - : A { - as_pair(const A& allocator, const T& value) - : A(allocator), - data(value) { - } - - T data; - }; - } -} - -#endif diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp index cca57b7..79bae59 100644 --- a/include/boost/smart_ptr/detail/array_allocator.hpp +++ b/include/boost/smart_ptr/detail/array_allocator.hpp @@ -9,40 +9,74 @@ #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP -#include #include +#include +#include #include -#if !defined(BOOST_NO_CXX11_ALLOCATOR) -#include -#endif +#include namespace boost { namespace detail { - template - struct ms_allocator_base; + template + struct as_size_base; - template - struct ms_allocator_base { - ms_allocator_base(std::size_t size_) - : size(size_ * sizeof(T)) { + template + struct as_size_base + : A { + as_size_base(const A& allocator, std::size_t size_) + : A(allocator), + size(size_ * array_total::size) { + } + + template + as_size_base(const as_size_base& other) + : A(other), + size(other.size) { } std::size_t size; }; - template - struct ms_allocator_base { + template + struct as_size_base + : A { + as_size_base(const A& allocator) + : A(allocator) { + } + + template + as_size_base(const as_size_base& other) + : A(other) { + } + enum { - size = N * sizeof(T) + size = array_total::size }; }; - template - class as_allocator - : ms_allocator_base { - using ms_allocator_base::size; + struct ms_init_tag { }; + struct ms_noinit_tag { }; - template + template + union ms_allocator_state { + ms_allocator_state(T** result_) + : result(result_) { + } + + T** result; + T* object; + }; + + template + class as_allocator +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + : as_size_base:: + template rebind_alloc > { +#else + : as_size_base::other> { +#endif + template friend class as_allocator; #if !defined(BOOST_NO_CXX11_ALLOCATOR) @@ -59,8 +93,10 @@ namespace boost { typedef typename A::template rebind::other CA; #endif + using as_size_base::size; + public: - typedef typename array_inner::type type; + typedef typename array_base::type type; #if !defined(BOOST_NO_CXX11_ALLOCATOR) typedef typename YT::value_type value_type; @@ -80,119 +116,164 @@ namespace boost { typedef typename YA::const_reference const_reference; #endif - template + template struct rebind { - typedef as_allocator other; + typedef as_allocator other; }; - as_allocator(const A& allocator, type** data) - : pair(allocator, data) { + as_allocator(const A& allocator, type** result) + : as_size_base(allocator), + data(result) { } - as_allocator(const A& allocator, std::size_t size_, type** data) - : ms_allocator_base(size_), - pair(allocator, data) { + as_allocator(const A& allocator, std::size_t size_, + type** result) + : as_size_base(allocator, size_), + data(result) { } template - as_allocator(const as_allocator& other) - : ms_allocator_base(other), - pair(other.pair, other.pair.data) { - } - - pointer address(reference value) const { - return pair.address(value); - } - - const_pointer address(const_reference value) const { - return pair.address(value); + as_allocator(const as_allocator& other) + : as_size_base(other), + data(other.data) { } +#if !defined(BOOST_NO_CXX11_ALLOCATOR) size_type max_size() const { - return pair.max_size(); + return YT::max_size(*this); } +#else + using YA::address; + using YA::max_size; +#endif pointer allocate(size_type count, const void* value = 0) { - std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(value_type) + a1 - 1; - CA ca(pair); + enum { + M = boost::alignment_of::value + }; + std::size_t n1 = count * sizeof(value_type); + std::size_t n2 = size * sizeof(type) + M - 1; + CA ca(*this); #if !defined(BOOST_NO_CXX11_ALLOCATOR) - char* p1 = CT::allocate(ca, size + n1, value); + void* p1 = CT::allocate(ca, n1 + n2, value); #else - char* p1 = ca.allocate(size + n1, value); + void* p1 = ca.allocate(n1 + n2, value); #endif - char* p2 = p1 + n1; - while (std::size_t(p2) % a1 != 0) { - p2--; - } - *pair.data = reinterpret_cast(p2); - return reinterpret_cast(p1); + void* p2 = static_cast(p1) + n1; + p2 = sp_align(M, p2); + *data.result = static_cast(p2); + return static_cast(p1); } void deallocate(pointer memory, size_type count) { - std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(value_type) + a1 - 1; + enum { + M = boost::alignment_of::value + }; + std::size_t n1 = count * sizeof(value_type); + std::size_t n2 = size * sizeof(type) + M - 1; char* p1 = reinterpret_cast(memory); - CA ca(pair); + CA ca(*this); #if !defined(BOOST_NO_CXX11_ALLOCATOR) - CT::deallocate(ca, p1, size + n1); + CT::deallocate(ca, p1, n1 + n2); #else - ca.deallocate(p1, size + n1); + ca.deallocate(p1, n1 + n2); #endif } - template + template void construct(U* memory, const_reference value) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) - YT::construct(pair, memory, value); - + YT::construct(*this, memory, value); #else - pair.construct(memory, value); + YA::construct(memory, value); #endif } - template + template void destroy(U* memory) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) - YT::destroy(pair, memory); + YT::destroy(*this, memory); #else - pair.destroy(memory); + YA::destroy(memory); #endif } #if !defined(BOOST_NO_CXX11_ALLOCATOR) && \ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template + template void construct(U* memory, Args&&... args) { - YT::construct(pair, memory, std::forward(args)...); + YT::construct(*this, memory, std::forward(args)...); } #endif - template - bool operator==(const as_allocator& other) const { - return pair == other.pair; + template + bool operator==(const as_allocator& other) const { + return true; } - template - bool operator!=(const as_allocator& other) const { - return !(*this == other); + template + bool operator!=(const as_allocator& other) const { + return !(*this == other); + } + + void set(type* memory) { + data.object = memory; + } + + void operator()() { + if (data.object) { + R tag; + free(tag); + } } private: - as_pair pair; + void free(ms_init_tag) { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + as_destroy(*this, data.object, size); +#else + ms_destroy(data.object, size); +#endif + } + + void free(ms_noinit_tag) { + ms_destroy(data.object, size); + } + + ms_allocator_state data; }; - template - class ms_allocator - : ms_allocator_base { - using ms_allocator_base::size; + template + struct ms_size_base; - template + template + struct ms_size_base { + ms_size_base(std::size_t size_) + : size(size_ * array_total::size) { + } + + std::size_t size; + }; + + template + struct ms_size_base { + enum { + size = array_total::size + }; + }; + + template + class ms_allocator + : ms_size_base { + using ms_size_base::size; + + template friend class ms_allocator; public: - typedef typename array_inner::type type; + typedef typename array_base::type type; + typedef Y value_type; typedef Y* pointer; typedef const Y* const_pointer; @@ -201,26 +282,27 @@ namespace boost { typedef Y& reference; typedef const Y& const_reference; - template + template struct rebind { - typedef ms_allocator other; + typedef ms_allocator other; }; - ms_allocator(type** data_) - : data(data_) { + ms_allocator(type** result) + : data(result) { } - ms_allocator(std::size_t size_, type** data_) - : ms_allocator_base(size_), - data(data_) { + ms_allocator(std::size_t size_, type** result) + : ms_size_base(size_), + data(result) { } template - ms_allocator(const ms_allocator& other) - : ms_allocator_base(other), + ms_allocator(const ms_allocator& other) + : ms_size_base(other), data(other.data) { } +#if defined(BOOST_NO_CXX11_ALLOCATOR) pointer address(reference value) const { return &value; } @@ -228,6 +310,7 @@ namespace boost { const_pointer address(const_reference value) const { return &value; } +#endif size_type max_size() const { enum { @@ -237,15 +320,16 @@ namespace boost { } pointer allocate(size_type count, const void* = 0) { - std::size_t a1 = boost::alignment_of::value; - std::size_t n1 = count * sizeof(value_type) + a1 - 1; - void* p1 = ::operator new(n1 + size); - char* p2 = static_cast(p1) + n1; - while (std::size_t(p2) % a1 != 0) { - p2--; - } - *data = reinterpret_cast(p2); - return reinterpret_cast(p1); + enum { + M = boost::alignment_of::value + }; + std::size_t n1 = count * sizeof(value_type); + std::size_t n2 = size * sizeof(type) + M - 1; + void* p1 = ::operator new(n1 + n2); + void* p2 = static_cast(p1) + n1; + p2 = sp_align(M, p2); + *data.result = static_cast(p2); + return static_cast(p1); } void deallocate(pointer memory, size_type) { @@ -253,13 +337,13 @@ namespace boost { ::operator delete(p1); } - template + template void construct(U* memory, const_reference value) { void* p1 = memory; ::new(p1) U(value); } - template + template void destroy(U* memory) { memory->~U(); } @@ -267,25 +351,41 @@ namespace boost { #if !defined(BOOST_NO_CXX11_ALLOCATOR) && \ !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) - template + template void construct(U* memory, Args&&... args) { void* p1 = memory; ::new(p1) U(std::forward(args)...); } #endif - template - bool operator==(const ms_allocator&) const { + template + bool operator==(const ms_allocator&) const { return true; } - template - bool operator!=(const ms_allocator& other) const { + template + bool operator!=(const ms_allocator& other) const { return !(*this == other); } + void set(type* memory) { + data.object = memory; + } + + void operator()() { + if (data.object) { + ms_destroy(data.object, size); + } + } + private: - type** data; + ms_allocator_state data; + }; + + class ms_in_allocator_tag { + public: + void operator()(const void*) { + } }; } } diff --git a/include/boost/smart_ptr/detail/array_count_impl.hpp b/include/boost/smart_ptr/detail/array_count_impl.hpp new file mode 100644 index 0000000..b7c9617 --- /dev/null +++ b/include/boost/smart_ptr/detail/array_count_impl.hpp @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_COUNT_IMPL_HPP +#define BOOST_SMART_PTR_DETAIL_ARRAY_COUNT_IMPL_HPP + +#include +#include + +namespace boost { + namespace detail { + template + class sp_counted_impl_pda + : public sp_counted_base { + typedef ms_in_allocator_tag D; + typedef sp_counted_impl_pda Y; + public: + sp_counted_impl_pda(P, D, const A& allocator_) + : allocator(allocator_) { + } + + virtual void dispose() { + allocator(); + } + + virtual void destroy() { +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + typedef typename std::allocator_traits:: + template rebind_alloc YA; + typedef typename std::allocator_traits:: + template rebind_traits YT; +#else + typedef typename A::template rebind::other YA; +#endif + YA a1(allocator); +#if !defined(BOOST_NO_CXX11_ALLOCATOR) + YT::destroy(a1, this); + YT::deallocate(a1, this, 1); +#else + this->~Y(); + a1.deallocate(this, 1); +#endif + } + + virtual void* get_deleter(const sp_typeinfo&) { + return &reinterpret_cast(allocator); + } + + virtual void* get_untyped_deleter() { + return &reinterpret_cast(allocator); + } + + private: + sp_counted_impl_pda(const sp_counted_impl_pda&); + sp_counted_impl_pda& operator=(const sp_counted_impl_pda&); + + A allocator; + }; + } +} + +#endif diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp deleted file mode 100644 index ca320dc..0000000 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2012-2014 Glen Joseph Fernandes - * glenfe at live dot com - * - * Distributed under the Boost Software License, - * Version 1.0. (See accompanying file LICENSE_1_0.txt - * or copy at http://boost.org/LICENSE_1_0.txt) - */ -#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP -#define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP - -#include -#include -#include - -namespace boost { - namespace detail { - template - struct ms_deleter_base; - - template - struct ms_deleter_base { - ms_deleter_base(std::size_t size_) - : size(size_) { - } - - std::size_t size; - }; - - template - struct ms_deleter_base { - enum { - size = N - }; - }; - - template - class as_deleter - : ms_deleter_base { - using ms_deleter_base::size; - - public: - typedef typename array_inner::type type; - -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - typedef typename std::allocator_traits:: - template rebind_alloc allocator; -#else - typedef typename A:: - template rebind::other allocator; -#endif - - as_deleter(const A& allocator_) - : pair(allocator_, 0) { - } - - as_deleter(const A& allocator_, std::size_t size_) - : ms_deleter_base(size_), - pair(allocator_, 0) { - } - - void set(type* memory) { - pair.data = memory; - } - - void operator()(const void*) { - if (pair.data) { - as_destroy(pair, pair.data, size); - } - } - - private: - as_pair pair; - }; - - template - class ms_deleter - : ms_deleter_base { - using ms_deleter_base::size; - - public: - typedef typename array_inner::type type; - - ms_deleter() - : object(0) { - } - - ms_deleter(std::size_t size_) - : ms_deleter_base(size_), - object(0) { - } - - void set(type* memory) { - object = memory; - } - - void operator()(const void*) { - if (object) { - ms_destroy(object, size); - } - } - - private: - type* object; - }; - } -} - -#endif diff --git a/include/boost/smart_ptr/detail/array_traits.hpp b/include/boost/smart_ptr/detail/array_traits.hpp index e10ef97..819c5ba 100644 --- a/include/boost/smart_ptr/detail/array_traits.hpp +++ b/include/boost/smart_ptr/detail/array_traits.hpp @@ -9,48 +9,48 @@ #ifndef BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP -#include +#include namespace boost { namespace detail { - template + template struct array_base { - typedef T type; + typedef typename boost::remove_cv::type type; }; - template + template struct array_base { typedef typename array_base::type type; }; - template + template struct array_base { typedef typename array_base::type type; }; - template + template struct array_total { enum { size = 1 }; }; - template + template struct array_total { enum { size = N * array_total::size }; }; - template + template struct array_inner; - template + template struct array_inner { typedef T type; }; - template + template struct array_inner { typedef T type; }; diff --git a/include/boost/smart_ptr/detail/array_utility.hpp b/include/boost/smart_ptr/detail/array_utility.hpp index e4b690c..84029a1 100644 --- a/include/boost/smart_ptr/detail/array_utility.hpp +++ b/include/boost/smart_ptr/detail/array_utility.hpp @@ -21,43 +21,24 @@ namespace boost { typedef boost::true_type ms_is_trivial; typedef boost::false_type ms_no_trivial; - template + template inline void ms_destroy(T*, std::size_t, ms_is_trivial) { } - template + template inline void ms_destroy(T* memory, std::size_t size, ms_no_trivial) { for (std::size_t i = size; i > 0;) { memory[--i].~T(); } } - template + template inline void ms_destroy(T* memory, std::size_t size) { boost::has_trivial_destructor trivial; ms_destroy(memory, size, trivial); } -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - template - inline void as_destroy(A& allocator, T* memory, - std::size_t size) { - typedef typename std::allocator_traits:: - template rebind_traits TT; - for (std::size_t i = size; i > 0;) { - TT::destroy(allocator, &memory[--i]); - } - } -#else - template - inline void as_destroy(const A&, T* memory, - std::size_t size) { - boost::has_trivial_destructor trivial; - ms_destroy(memory, size, trivial); - } -#endif - - template + template inline void ms_init(T* memory, std::size_t size, ms_is_trivial) { for (std::size_t i = 0; i < size; i++) { void* p1 = memory + i; @@ -65,7 +46,7 @@ namespace boost { } } - template + template inline void ms_init(T* memory, std::size_t size, ms_no_trivial) { #if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; @@ -86,15 +67,48 @@ namespace boost { #endif } - template + template inline void ms_init(T* memory, std::size_t size) { boost::has_trivial_default_constructor trivial; ms_init(memory, size, trivial); } + template + inline void ms_init(T* memory, std::size_t size, const T* list) { +#if !defined(BOOST_NO_EXCEPTIONS) + std::size_t i = 0; + try { + for (; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % N]); + } + } catch (...) { + ms_destroy(memory, i); + throw; + } +#else + for (std::size_t i = 0; i < size; i++) { + void* p1 = memory + i; + ::new(p1) T(list[i % N]); + } +#endif + } #if !defined(BOOST_NO_CXX11_ALLOCATOR) - template + template + inline void as_destroy(const A& allocator, T* memory, + std::size_t size) { + typedef typename std::allocator_traits:: + template rebind_alloc TA; + typedef typename std::allocator_traits:: + template rebind_traits TT; + TA a2(allocator); + for (std::size_t i = size; i > 0;) { + TT::destroy(a2, &memory[--i]); + } + } + + template inline void as_init(const A& allocator, T* memory, std::size_t size, ms_is_trivial) { typedef typename std::allocator_traits:: @@ -107,8 +121,8 @@ namespace boost { } } - template - inline void as_init(const A& allocator, T* memory, std::size_t size, + template + inline void as_init(const A& allocator, T* memory, std::size_t size, ms_no_trivial) { typedef typename std::allocator_traits:: template rebind_alloc TA; @@ -132,42 +146,13 @@ namespace boost { #endif } - template + template inline void as_init(const A& allocator, T* memory, std::size_t size) { boost::has_trivial_default_constructor trivial; as_init(allocator, memory, size, trivial); } -#else - template - inline void as_init(const A&, T* memory, std::size_t size) { - boost::has_trivial_default_constructor trivial; - ms_init(memory, size, trivial); - } -#endif - template - inline void ms_init(T* memory, std::size_t size, const T* list) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % N]); - } - } catch (...) { - ms_destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % N]); - } -#endif - } - -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - template + template inline void as_init(const A& allocator, T* memory, std::size_t size, const T* list) { typedef typename std::allocator_traits:: @@ -191,35 +176,13 @@ namespace boost { } #endif } -#else - template - inline void as_init(const A&, T* memory, std::size_t size, - const T* list) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % N]); - } - } catch (...) { - ms_destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % N]); - } -#endif - } #endif - template + template inline void ms_noinit(T*, std::size_t, ms_is_trivial) { } - template + template inline void ms_noinit(T* memory, std::size_t size, ms_no_trivial) { #if !defined(BOOST_NO_EXCEPTIONS) std::size_t i = 0; @@ -240,7 +203,7 @@ namespace boost { #endif } - template + template inline void ms_noinit(T* memory, std::size_t size) { boost::has_trivial_default_constructor trivial; ms_noinit(memory, size, trivial); diff --git a/include/boost/smart_ptr/detail/sp_align.hpp b/include/boost/smart_ptr/detail/sp_align.hpp new file mode 100644 index 0000000..5a616ee --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_align.hpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_SP_ALIGN_HPP +#define BOOST_SMART_PTR_DETAIL_SP_ALIGN_HPP + +#include + +namespace boost { + namespace detail { + inline void* sp_align(std::size_t alignment, void* ptr) { + std::size_t n1 = (std::size_t)ptr % alignment; + if (n1 != 0) { + ptr = (char*)ptr + alignment - n1; + } + return ptr; + } + } +} + +#endif diff --git a/include/boost/smart_ptr/detail/sp_if_array.hpp b/include/boost/smart_ptr/detail/sp_if_array.hpp index bbd0f3c..9a2c1e0 100644 --- a/include/boost/smart_ptr/detail/sp_if_array.hpp +++ b/include/boost/smart_ptr/detail/sp_if_array.hpp @@ -13,18 +13,18 @@ namespace boost { namespace detail { - template + template struct sp_if_array; - template + template struct sp_if_array { typedef boost::shared_ptr type; }; - template + template struct sp_if_size_array; - template + template struct sp_if_size_array { typedef boost::shared_ptr type; }; diff --git a/include/boost/smart_ptr/detail/sp_interlocked.hpp b/include/boost/smart_ptr/detail/sp_interlocked.hpp new file mode 100644 index 0000000..814b0c2 --- /dev/null +++ b/include/boost/smart_ptr/detail/sp_interlocked.hpp @@ -0,0 +1,152 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SP_INTERLOCKED_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SP_INTERLOCKED_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// boost/detail/sp_interlocked.hpp +// +// Copyright 2005, 2014 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +#include + +// BOOST_SP_HAS_INTRIN_H + +// VC9 has intrin.h, but it collides with +#if defined( BOOST_MSVC ) && BOOST_MSVC >= 1600 + +# define BOOST_SP_HAS_INTRIN_H + +// Unlike __MINGW64__, __MINGW64_VERSION_MAJOR is defined by MinGW-w64 for both 32 and 64-bit targets. +#elif defined( __MINGW64_VERSION_MAJOR ) + +// MinGW-w64 provides intrin.h for both 32 and 64-bit targets. +# define BOOST_SP_HAS_INTRIN_H + +// Intel C++ on Windows on VC10+ stdlib +#elif defined( BOOST_INTEL_WIN ) && defined( _CPPLIB_VER ) && _CPPLIB_VER >= 520 + +# define BOOST_SP_HAS_INTRIN_H + +#endif + +#if defined( BOOST_USE_WINDOWS_H ) + +# include + +# define BOOST_SP_INTERLOCKED_INCREMENT InterlockedIncrement +# define BOOST_SP_INTERLOCKED_DECREMENT InterlockedDecrement +# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE InterlockedExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd + +#elif defined( BOOST_USE_INTRIN_H ) || defined( BOOST_SP_HAS_INTRIN_H ) + +#include + +# define BOOST_SP_INTERLOCKED_INCREMENT _InterlockedIncrement +# define BOOST_SP_INTERLOCKED_DECREMENT _InterlockedDecrement +# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE _InterlockedExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd + +#elif defined( _WIN32_WCE ) + +#if _WIN32_WCE >= 0x600 + +extern "C" long __cdecl _InterlockedIncrement( long volatile * ); +extern "C" long __cdecl _InterlockedDecrement( long volatile * ); +extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long ); +extern "C" long __cdecl _InterlockedExchange( long volatile *, long ); +extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long ); + +# define BOOST_SP_INTERLOCKED_INCREMENT _InterlockedIncrement +# define BOOST_SP_INTERLOCKED_DECREMENT _InterlockedDecrement +# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE _InterlockedExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd + +#else + +// under Windows CE we still have old-style Interlocked* functions + +extern "C" long __cdecl InterlockedIncrement( long* ); +extern "C" long __cdecl InterlockedDecrement( long* ); +extern "C" long __cdecl InterlockedCompareExchange( long*, long, long ); +extern "C" long __cdecl InterlockedExchange( long*, long ); +extern "C" long __cdecl InterlockedExchangeAdd( long*, long ); + +# define BOOST_SP_INTERLOCKED_INCREMENT InterlockedIncrement +# define BOOST_SP_INTERLOCKED_DECREMENT InterlockedDecrement +# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE InterlockedExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd + +#endif + +#elif defined( BOOST_MSVC ) || defined( BOOST_INTEL_WIN ) + +#if defined( __CLRCALL_PURE_OR_CDECL ) + +extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedIncrement( long volatile * ); +extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedDecrement( long volatile * ); +extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedCompareExchange( long volatile *, long, long ); +extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedExchange( long volatile *, long ); +extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedExchangeAdd( long volatile *, long ); + +#else + +extern "C" long __cdecl _InterlockedIncrement( long volatile * ); +extern "C" long __cdecl _InterlockedDecrement( long volatile * ); +extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long ); +extern "C" long __cdecl _InterlockedExchange( long volatile *, long ); +extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long ); + +#endif + +# define BOOST_SP_INTERLOCKED_INCREMENT _InterlockedIncrement +# define BOOST_SP_INTERLOCKED_DECREMENT _InterlockedDecrement +# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE _InterlockedExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd + +#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) + +namespace boost +{ + +namespace detail +{ + +extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement( long volatile * ); +extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement( long volatile * ); +extern "C" __declspec(dllimport) long __stdcall InterlockedCompareExchange( long volatile *, long, long ); +extern "C" __declspec(dllimport) long __stdcall InterlockedExchange( long volatile *, long ); +extern "C" __declspec(dllimport) long __stdcall InterlockedExchangeAdd( long volatile *, long ); + +} // namespace detail + +} // namespace boost + +# define BOOST_SP_INTERLOCKED_INCREMENT ::boost::detail::InterlockedIncrement +# define BOOST_SP_INTERLOCKED_DECREMENT ::boost::detail::InterlockedDecrement +# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE ::boost::detail::InterlockedCompareExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE ::boost::detail::InterlockedExchange +# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD ::boost::detail::InterlockedExchangeAdd + +#else + +# error "Interlocked intrinsics not available" + +#endif + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_INTERLOCKED_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/spinlock.hpp b/include/boost/smart_ptr/detail/spinlock.hpp index 88d7ad6..deffb67 100644 --- a/include/boost/smart_ptr/detail/spinlock.hpp +++ b/include/boost/smart_ptr/detail/spinlock.hpp @@ -31,7 +31,10 @@ #include #include -#if defined( BOOST_SP_USE_PTHREADS ) +#if defined( BOOST_SP_USE_STD_ATOMIC ) +# include + +#elif defined( BOOST_SP_USE_PTHREADS ) # include #elif defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ ) diff --git a/include/boost/smart_ptr/detail/spinlock_std_atomic.hpp b/include/boost/smart_ptr/detail/spinlock_std_atomic.hpp new file mode 100644 index 0000000..a61c1cd --- /dev/null +++ b/include/boost/smart_ptr/detail/spinlock_std_atomic.hpp @@ -0,0 +1,83 @@ +#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED +#define BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED + +// MS compatible compilers support #pragma once + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +# pragma once +#endif + +// +// Copyright (c) 2014 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// + +#include +#include + +namespace boost +{ + +namespace detail +{ + +class spinlock +{ +public: + + std::atomic_flag v_; + +public: + + bool try_lock() + { + return !v_.test_and_set( std::memory_order_acquire ); + } + + void lock() + { + for( unsigned k = 0; !try_lock(); ++k ) + { + boost::detail::yield( k ); + } + } + + void unlock() + { + v_ .clear( std::memory_order_release ); + } + +public: + + class scoped_lock + { + private: + + spinlock & sp_; + + scoped_lock( scoped_lock const & ); + scoped_lock & operator=( scoped_lock const & ); + + public: + + explicit scoped_lock( spinlock & sp ): sp_( sp ) + { + sp.lock(); + } + + ~scoped_lock() + { + sp_.unlock(); + } + }; +}; + +} // namespace detail +} // namespace boost + +#define BOOST_DETAIL_SPINLOCK_INIT { ATOMIC_FLAG_INIT } + +#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED diff --git a/include/boost/smart_ptr/detail/up_if_array.hpp b/include/boost/smart_ptr/detail/up_if_array.hpp index d0b197d..7e62d10 100644 --- a/include/boost/smart_ptr/detail/up_if_array.hpp +++ b/include/boost/smart_ptr/detail/up_if_array.hpp @@ -13,10 +13,10 @@ namespace boost { namespace detail { - template + template struct up_if_array; - template + template struct up_if_array { typedef std::unique_ptr type; }; diff --git a/include/boost/smart_ptr/detail/up_if_not_array.hpp b/include/boost/smart_ptr/detail/up_if_not_array.hpp index 7679e61..fd74f25 100644 --- a/include/boost/smart_ptr/detail/up_if_not_array.hpp +++ b/include/boost/smart_ptr/detail/up_if_not_array.hpp @@ -13,16 +13,16 @@ namespace boost { namespace detail { - template + template struct up_if_not_array { typedef std::unique_ptr type; }; - template + template struct up_if_not_array { }; - template + template struct up_if_not_array { }; } diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index 50763d8..8c2c5d0 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -9,151 +9,155 @@ #ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP -#include -#include +#include #include -#include namespace boost { - template + template inline typename boost::detail::sp_if_array::type make_shared(std::size_t size) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_deleter D1; - T1* p1 = 0; - T3* p2 = 0; + typedef boost::detail::ms_init_tag R1; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; std::size_t n1 = size * boost::detail::array_total::size; - D1 d1(n1); - A1 a1(n1, &p2); - boost::shared_ptr s1(p1, d1, a1); - p1 = reinterpret_cast(p2); + T1* p1 = 0; + T2* p2 = 0; + D1 d1; + A1 a1(size, &p2); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); boost::detail::ms_init(p2, n1); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); + a2->set(p2); + p1 = reinterpret_cast(p2); + return shared_ptr(s1, p1); } - template + template inline typename boost::detail::sp_if_size_array::type make_shared() { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; + typedef boost::detail::ms_init_tag R1; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; enum { N = boost::detail::array_total::size }; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_deleter D1; T1* p1 = 0; - T3* p2 = 0; + T2* p2 = 0; D1 d1; A1 a1(&p2); - boost::shared_ptr s1(p1, d1, a1); - p1 = reinterpret_cast(p2); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); boost::detail::ms_init(p2, N); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); + a2->set(p2); + p1 = reinterpret_cast(p2); + return shared_ptr(s1, p1); } - template + template inline typename boost::detail::sp_if_array::type make_shared(std::size_t size, const typename boost::detail::array_inner::type& value) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; - typedef const T2 T4; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_deleter D1; + typedef const T2 T3; + typedef boost::detail::ms_init_tag R1; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; enum { M = boost::detail::array_total::size }; - T1* p1 = 0; - T3* p2 = 0; - T4* p3 = reinterpret_cast(&value); std::size_t n1 = M * size; - D1 d1(n1); - A1 a1(n1, &p2); - boost::shared_ptr s1(p1, d1, a1); + T1* p1 = 0; + T2* p2 = 0; + T3* p3 = reinterpret_cast(&value); + D1 d1; + A1 a1(size, &p2); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); + boost::detail::ms_init(p2, n1, p3); + a2->set(p2); p1 = reinterpret_cast(p2); - boost::detail::ms_init(p2, n1, p3); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); + return shared_ptr(s1, p1); } - template + template inline typename boost::detail::sp_if_size_array::type make_shared(const typename boost::detail::array_inner::type& value) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; - typedef const T2 T4; + typedef const T2 T3; + typedef boost::detail::ms_init_tag R1; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; enum { M = boost::detail::array_total::size, N = boost::detail::array_total::size }; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_deleter D1; T1* p1 = 0; - T3* p2 = 0; - T4* p3 = reinterpret_cast(&value); + T2* p2 = 0; + T3* p3 = reinterpret_cast(&value); D1 d1; A1 a1(&p2); - boost::shared_ptr s1(p1, d1, a1); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); + boost::detail::ms_init(p2, N, p3); + a2->set(p2); p1 = reinterpret_cast(p2); - boost::detail::ms_init(p2, N, p3); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); + return shared_ptr(s1, p1); } - template + template inline typename boost::detail::sp_if_array::type make_shared_noinit(std::size_t size) { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_deleter D1; - T1* p1 = 0; - T3* p2 = 0; + typedef boost::detail::ms_noinit_tag R1; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; std::size_t n1 = size * boost::detail::array_total::size; - D1 d1(n1); - A1 a1(n1, &p2); - boost::shared_ptr s1(p1, d1, a1); - p1 = reinterpret_cast(p2); + T1* p1 = 0; + T2* p2 = 0; + D1 d1; + A1 a1(size, &p2); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); boost::detail::ms_noinit(p2, n1); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); + a2->set(p2); + p1 = reinterpret_cast(p2); + return shared_ptr(s1, p1); } - template + template inline typename boost::detail::sp_if_size_array::type make_shared_noinit() { typedef typename boost::detail::array_inner::type T1; typedef typename boost::detail::array_base::type T2; - typedef typename boost::remove_cv::type T3; + typedef boost::detail::ms_noinit_tag R1; + typedef boost::detail::ms_allocator A1; + typedef boost::detail::ms_in_allocator_tag D1; enum { N = boost::detail::array_total::size }; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_deleter D1; T1* p1 = 0; - T3* p2 = 0; + T2* p2 = 0; D1 d1; A1 a1(&p2); - boost::shared_ptr s1(p1, d1, a1); - p1 = reinterpret_cast(p2); + shared_ptr s1(p1, d1, a1); + A1* a2 = static_cast(s1._internal_get_untyped_deleter()); + a2->set(0); boost::detail::ms_noinit(p2, N); - D1* d2 = static_cast(s1._internal_get_untyped_deleter()); - d2->set(p2); - return boost::shared_ptr(s1, p1); + a2->set(p2); + p1 = reinterpret_cast(p2); + return shared_ptr(s1, p1); } } diff --git a/include/boost/smart_ptr/make_unique_array.hpp b/include/boost/smart_ptr/make_unique_array.hpp index 987c565..eb0528e 100644 --- a/include/boost/smart_ptr/make_unique_array.hpp +++ b/include/boost/smart_ptr/make_unique_array.hpp @@ -13,14 +13,14 @@ #include namespace boost { - template + template inline typename boost::detail::up_if_array::type make_unique(std::size_t size) { typedef typename boost::detail::array_inner::type U; return std::unique_ptr(new U[size]()); } - template + template inline typename boost::detail::up_if_array::type make_unique_noinit(std::size_t size) { typedef typename boost::detail::array_inner::type U; diff --git a/include/boost/smart_ptr/make_unique_object.hpp b/include/boost/smart_ptr/make_unique_object.hpp index 12149c5..c392e24 100644 --- a/include/boost/smart_ptr/make_unique_object.hpp +++ b/include/boost/smart_ptr/make_unique_object.hpp @@ -14,27 +14,27 @@ #include namespace boost { - template + template inline typename boost::detail::up_if_not_array::type make_unique() { return std::unique_ptr(new T()); } #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template + template inline typename boost::detail::up_if_not_array::type make_unique(Args&&... args) { return std::unique_ptr(new T(std::forward(args)...)); } #endif - template + template inline typename boost::detail::up_if_not_array::type make_unique(T&& value) { return std::unique_ptr(new T(std::move(value))); } - template + template inline typename boost::detail::up_if_not_array::type make_unique_noinit() { return std::unique_ptr(new T); diff --git a/make_shared_array.html b/make_shared_array.html index 6c323b8..ebfaeda 100644 --- a/make_shared_array.html +++ b/make_shared_array.html @@ -30,50 +30,50 @@ user-supplied allocator, allowing finer control.

Synopsis

namespace boost {
-    template<typename U> // U is T[]
+    template<class U> // U is T[]
     shared_ptr<U> make_shared(size_t size);
 
-    template<typename U, typename A> // U is T[]
+    template<class U, class A> // U is T[]
     shared_ptr<U> allocate_shared(const A& allocator, size_t size);
 
-    template<typename U> // U is T[N]
+    template<class U> // U is T[N]
     shared_ptr<U> make_shared();
 
-    template<typename U, typename A> // U is T[N]
+    template<class U, class A> // U is T[N]
     shared_ptr<U> allocate_shared(const A& allocator);
 
-    template<typename U> // U is T[]
+    template<class U> // U is T[]
     shared_ptr<U> make_shared(size_t size, const T& value);
 
-    template<typename U, typename A>  // U is T[]
+    template<class U, class A>  // U is T[]
     shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T& value);
 
-    template<typename U> // U is T[N]
+    template<class U> // U is T[N]
     shared_ptr<U> make_shared(const T& value);
 
-    template<typename U, typename A> // U is T[N]
+    template<class U, class A> // U is T[N]
     shared_ptr<U> allocate_shared(const A& allocator, const T& value);
 
-    template<typename U> // U is T[]
+    template<class U> // U is T[]
     shared_ptr<U> make_shared_noinit(size_t size);
 
-    template<typename U, typename A> // U is T[]
+    template<class U, class A> // U is T[]
     shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);
 
-    template<typename U> // U is T[N]
+    template<class U> // U is T[N]
     shared_ptr<U> make_shared_noinit();
 
-    template<typename U, typename A> // U is T[N]
+    template<class U, class A> // U is T[N]
     shared_ptr<U> allocate_shared_noinit(const A& allocator);
 }

Common Requirements

-
template<typename U>
+    
template<class U>
     shared_ptr<U> make_shared(args);
-template<typename U, typename A>
+template<class U, class A>
     shared_ptr<U> allocate_shared(const A& allocator, args);
-template<typename U>
+template<class U>
     shared_ptr<U> make_shared_noinit(args);
-template<typename U, typename A>
+template<class U, class A>
     shared_ptr<U> allocate_shared_noinit(const A& allocator, args);

Requires: U is of the form T[] or @@ -157,9 +157,9 @@ template<typename U, typename A> structures such as the reference counts.

Free Functions

-
template<typename U> 
+    
template<class U> 
     shared_ptr<U> make_shared(size_t size);
-template<typename U, typename A> 
+template<class U, class A> 
     shared_ptr<U> allocate_shared(const A& allocator, size_t size);

Returns: A shared_ptr to a value-initialized @@ -172,9 +172,9 @@ template<typename U, typename A> boost::shared_ptr<int[][2]> a2 = boost::make_shared<int[][2]>(size);

-
template<typename U> 
+    
template<class U> 
     shared_ptr<U> make_shared();
-template<typename U, typename A> 
+template<class U, class A> 
     shared_ptr<U> allocate_shared(const A& allocator);

Returns: A shared_ptr to a value-initialized @@ -187,9 +187,9 @@ template<typename U, typename A> boost::shared_ptr<int[4][2]> a2 = boost::make_shared<int[4][2]>();

-
template<typename U> 
+    
template<class U> 
     shared_ptr<U> make_shared(size_t size, const T& value);
-template<typename U, typename A> 
+template<class U, class A> 
     shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T& value);

Returns: A shared_ptr to an object of type @@ -203,9 +203,9 @@ template<typename U, typename A> boost::shared_ptr<int[][2]> a2 = boost::make_shared<int[][2]>(size, {1, 2});

-
template<typename U> 
+    
template<class U> 
     shared_ptr<U> make_shared(const T& value);
-template<typename U, typename A> 
+template<class U, class A> 
     shared_ptr<U> allocate_shared(const A& allocator, const T& value);

Returns: A shared_ptr to an object of type @@ -219,9 +219,9 @@ template<typename U, typename A> boost::shared_ptr<int[4][2]> a2 = boost::make_shared<int[4][2]>({1, 2});

-
template<typename U> 
+    
template<class U> 
     shared_ptr<U> make_shared_noinit(size_t size);
-template<typename U, typename A> 
+template<class U, class A> 
     shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);

Returns: A shared_ptr to a default-initialized @@ -234,9 +234,9 @@ template<typename U, typename A> boost::shared_ptr<int[][2]> a2 = boost::make_shared_noinit<int[][2]>(size);

-
template<typename U> 
+    
template<class U> 
     shared_ptr<U> make_shared_noinit();
-template<typename U, typename A> 
+template<class U, class A> 
     shared_ptr<U> allocate_shared_noinit(const A& allocator);

Returns: A shared_ptr to a default-initialized @@ -252,8 +252,9 @@ boost::shared_ptr<int[4][2]> a2 = boost::make_shared_noinit<int[4][2]&g

History

February 2014. Glen Fernandes updated overloads of make_shared and allocate_shared to conform to the specification in C++ standard paper - N3870 including resolving C++ standard library - defect report 2070.

+ N3870, including resolving C++ standard library + defect report 2070, and reduced the spatial overhead of the internal + bookkeeping structures.

November 2012. Glen Fernandes contributed implementations of make_shared and allocate_shared for arrays.

References

diff --git a/make_unique.html b/make_unique.html index c3e6ab8..5b414e8 100644 --- a/make_unique.html +++ b/make_unique.html @@ -18,30 +18,30 @@ unique_ptr objects.

Synopsis

namespace boost {
-    template<typename U> // U is not array
+    template<class U> // U is not array
     unique_ptr<U> make_unique();
 
 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-    template<typename U, typename... Args> // U is not array
+    template<class U, class... Args> // U is not array
     unique_ptr<U> make_unique(Args&&... args);
 #endif
 
-    template<typename U> // U is not array
+    template<class U> // U is not array
     unique_ptr<U> make_unique(U&& value);
 
-    template<typename U> // U is T[]
+    template<class U> // U is T[]
     unique_ptr<U> make_unique(size_t size);
 
-    template<typename U> // U is not array
+    template<class U> // U is not array
     unique_ptr<U> make_unique_noinit();
 
-    template<typename U> // U is T[]
+    template<class U> // U is T[]
     unique_ptr<U> make_unique_noinit(size_t size);
 }

Common Requirements

-
template<typename U>
+    
template<class U>
     unique_ptr<U> make_unique(args);
-template<typename U>
+template<class U>
     unique_ptr<U> make_unique_noinit(args);

Effects: Allocates memory for an object of type U @@ -73,7 +73,7 @@ template<typename U>

Free Functions

-
template<typename U, typename... Args>
+    
template<class U, class... Args>
 unique_ptr<U> make_unique(Args&&... args);

Returns: A unique_ptr to an object of type U, @@ -86,7 +86,7 @@ unique_ptr<U> make_unique(Args&&... args);

unique_ptr<point> p2 = boost::make_unique<point>(x, y);
-
template<typename U>
+    
template<class U>
 unique_ptr<U> make_unique(U&& value);

Returns: A unique_ptr to an object of type U, @@ -99,7 +99,7 @@ unique_ptr<U> make_unique(U&& value);

unique_ptr<point> p2 = boost::make_unique<point>({-10, 25});
-
template<typename U>
+    
template<class U>
 unique_ptr<U> make_unique(size_t size);

Returns: A unique_ptr to a value-initialized object of type @@ -112,7 +112,7 @@ unique_ptr<U> make_unique(size_t size);

unique_ptr<int[][2]> p2 = boost::make_unique<int[][2]>(2); -
template<typename U>
+    
template<class U>
 unique_ptr<U> make_unique_noinit();

Returns: A unique_ptr to a default-initialized object of @@ -125,7 +125,7 @@ unique_ptr<U> make_unique_noinit();

unique_ptr<point> p2 = boost::make_unique_noinit<point>(); -
template<typename U>
+    
template<class U>
 unique_ptr<U> make_unique_noinit(size_t size);

Returns: A unique_ptr to a default-initialized object of diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index fc95688..19520c2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -83,6 +83,7 @@ import testing ; [ run shared_ptr_alloc11_test.cpp ] [ run allocate_shared_alloc11_test.cpp ] [ run allocate_shared_construct11_test.cpp ] + [ run sp_interlocked_test.cpp ] [ compile-fail array_fail_spa_sp_c.cpp ] [ compile-fail array_fail_sp_spa_c.cpp ] diff --git a/test/sp_interlocked_test.cpp b/test/sp_interlocked_test.cpp new file mode 100644 index 0000000..1b075b4 --- /dev/null +++ b/test/sp_interlocked_test.cpp @@ -0,0 +1,60 @@ +// +// sp_interlocked_test.cpp +// +// Copyright 2014 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 +// + +#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ ) + +#include +#include + +int main() +{ + long x = 0, r; + + r = BOOST_SP_INTERLOCKED_INCREMENT( &x ); + + BOOST_TEST( x == 1 ); + BOOST_TEST( r == 1 ); + + r = BOOST_SP_INTERLOCKED_DECREMENT( &x ); + + BOOST_TEST( x == 0 ); + BOOST_TEST( r == 0 ); + + r = BOOST_SP_INTERLOCKED_EXCHANGE( &x, 3 ); + + BOOST_TEST( x == 3 ); + BOOST_TEST( r == 0 ); + + r = BOOST_SP_INTERLOCKED_EXCHANGE_ADD( &x, 2 ); + + BOOST_TEST( x == 5 ); + BOOST_TEST( r == 3 ); + + r = BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE( &x, 0, 3 ); + + BOOST_TEST( x == 5 ); + BOOST_TEST( r == 5 ); + + r = BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE( &x, 0, 5 ); + + BOOST_TEST( x == 0 ); + BOOST_TEST( r == 5 ); + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} + +#endif