summaryrefslogtreecommitdiff
path: root/boost/smart_ptr/allocate_shared_array.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/smart_ptr/allocate_shared_array.hpp')
-rw-r--r--boost/smart_ptr/allocate_shared_array.hpp983
1 files changed, 327 insertions, 656 deletions
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 */