Simplify ms_allocator and as_allocator design

This commit is contained in:
Glen Fernandes
2014-02-28 10:16:22 -08:00
parent 71b2f87e35
commit 75add10b1d
4 changed files with 149 additions and 236 deletions

View File

@ -19,7 +19,7 @@ namespace boost {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_init_tag R1; typedef boost::detail::ms_init_tag R1;
typedef boost::detail::as_allocator<T, R1, A> A1; typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
std::size_t n1 = size * boost::detail::array_total<T1>::size; std::size_t n1 = size * boost::detail::array_total<T1>::size;
T1* p1 = 0; T1* p1 = 0;
@ -45,7 +45,7 @@ namespace boost {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_init_tag R1; typedef boost::detail::ms_init_tag R1;
typedef boost::detail::as_allocator<T, R1, A> A1; typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
enum { enum {
N = boost::detail::array_total<T>::size N = boost::detail::array_total<T>::size
@ -75,7 +75,7 @@ namespace boost {
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3; typedef const T2 T3;
typedef boost::detail::ms_init_tag R1; typedef boost::detail::ms_init_tag R1;
typedef boost::detail::as_allocator<T, R1, A> A1; typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
enum { enum {
M = boost::detail::array_total<T1>::size M = boost::detail::array_total<T1>::size
@ -107,7 +107,7 @@ namespace boost {
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3; typedef const T2 T3;
typedef boost::detail::ms_init_tag R1; typedef boost::detail::ms_init_tag R1;
typedef boost::detail::as_allocator<T, R1, A> A1; typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
enum { enum {
N = boost::detail::array_total<T>::size, N = boost::detail::array_total<T>::size,
@ -137,7 +137,7 @@ namespace boost {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_noinit_tag R1; typedef boost::detail::ms_noinit_tag R1;
typedef boost::detail::as_allocator<T, R1, A> A1; typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
std::size_t n1 = size * boost::detail::array_total<T1>::size; std::size_t n1 = size * boost::detail::array_total<T1>::size;
T1* p1 = 0; T1* p1 = 0;
@ -159,7 +159,7 @@ namespace boost {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_noinit_tag R1; typedef boost::detail::ms_noinit_tag R1;
typedef boost::detail::as_allocator<T, R1, A> A1; typedef boost::detail::as_allocator<A, T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
enum { enum {
N = boost::detail::array_total<T>::size N = boost::detail::array_total<T>::size

View File

@ -13,151 +13,129 @@
#include <boost/smart_ptr/detail/array_utility.hpp> #include <boost/smart_ptr/detail/array_utility.hpp>
#include <boost/smart_ptr/detail/sp_align.hpp> #include <boost/smart_ptr/detail/sp_align.hpp>
#include <boost/type_traits/alignment_of.hpp> #include <boost/type_traits/alignment_of.hpp>
#include <algorithm>
namespace boost { namespace boost {
namespace detail { namespace detail {
template<class T, class A> struct ms_init_tag { };
struct as_size_base; struct ms_noinit_tag { };
template<class T, class A> template<class T>
struct as_size_base<T[], A> class ms_allocator_state;
: A {
as_size_base(const A& allocator, std::size_t size_)
: A(allocator),
size(size_ * array_total<T>::size) {
}
template<class U> template<class T>
as_size_base(const as_size_base<T[], U>& other) struct ms_allocator_state<T[]> {
: A(other), typedef typename array_base<T>::type type;
size(other.size) {
ms_allocator_state(std::size_t size_,
type** result_)
: size(size_ * array_total<T>::size),
result(result_) {
} }
std::size_t size; std::size_t size;
union {
type** result;
type* object;
};
}; };
template<class T, std::size_t N, class A> template<class T, std::size_t N>
struct as_size_base<T[N], A> struct ms_allocator_state<T[N]> {
: A { typedef typename array_base<T>::type type;
as_size_base(const A& allocator)
: A(allocator) {
}
template<class U> ms_allocator_state(type** result_)
as_size_base(const as_size_base<T[N], U>& other) : result(result_) {
: A(other) {
} }
enum { enum {
size = array_total<T[N]>::size size = array_total<T[N]>::size
}; };
union {
type** result;
type* object;
};
}; };
struct ms_init_tag { }; template<class A, class T, class R>
struct ms_noinit_tag { };
template<class T>
union ms_allocator_state {
ms_allocator_state(T** result_)
: result(result_) {
}
T** result;
T* object;
};
template<class T, class R, class A, class Y = char>
class as_allocator class as_allocator
#if !defined(BOOST_NO_CXX11_ALLOCATOR) : public A {
: as_size_base<T, typename std::allocator_traits<A>:: template<class A_, class T_, class R_>
template rebind_alloc<Y> > {
#else
: as_size_base<T, typename A::
template rebind<Y>::other> {
#endif
template<class T_, class R_, class A_, class Y_>
friend class as_allocator; friend class as_allocator;
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename std::allocator_traits<A>:: typedef std::allocator_traits<A> AT;
template rebind_alloc<Y> YA; typedef typename AT::template rebind_alloc<char> CA;
typedef typename std::allocator_traits<A>:: typedef typename AT::template rebind_traits<char> CT;
template rebind_alloc<char> CA;
typedef typename std::allocator_traits<A>::
template rebind_traits<Y> YT;
typedef typename std::allocator_traits<A>::
template rebind_traits<char> CT;
#else #else
typedef typename A::template rebind<Y>::other YA;
typedef typename A::template rebind<char>::other CA; typedef typename A::template rebind<char>::other CA;
#endif #endif
using as_size_base<T, YA>::size;
public: public:
typedef typename array_base<T>::type type; typedef A allocator_type;
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename YT::value_type value_type; typedef typename AT::value_type value_type;
typedef typename YT::pointer pointer; typedef typename AT::pointer pointer;
typedef typename YT::const_pointer const_pointer; typedef typename AT::const_pointer const_pointer;
typedef typename YT::size_type size_type; typedef typename AT::void_pointer void_pointer;
typedef typename YT::difference_type difference_type; typedef typename AT::const_void_pointer const_void_pointer;
typedef Y& reference; typedef typename AT::size_type size_type;
typedef const Y& const_reference; typedef typename AT::difference_type difference_type;
#else #else
typedef typename YA::value_type value_type; typedef typename A::value_type value_type;
typedef typename YA::pointer pointer; typedef typename A::pointer pointer;
typedef typename YA::const_pointer const_pointer; typedef typename A::const_pointer const_pointer;
typedef typename YA::size_type size_type; typedef typename A::size_type size_type;
typedef typename YA::difference_type difference_type; typedef typename A::difference_type difference_type;
typedef typename YA::reference reference; typedef typename A::reference reference;
typedef typename YA::const_reference const_reference; typedef typename A::const_reference const_reference;
typedef void* void_pointer;
typedef const void* const_void_pointer;
#endif #endif
template<class U> template<class U>
struct rebind { struct rebind {
typedef as_allocator<T, R, A, U> other; #if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef as_allocator<typename AT::
template rebind_alloc<U>, T, R> other;
#else
typedef as_allocator<typename A::
template rebind<U>::other, T, R> other;
#endif
}; };
typedef typename array_base<T>::type type;
as_allocator(const A& allocator, type** result) as_allocator(const A& allocator, type** result)
: as_size_base<T, YA>(allocator), : A(allocator),
data(result) { data(result) {
} }
as_allocator(const A& allocator, std::size_t size_, as_allocator(const A& allocator, std::size_t size,
type** result) type** result)
: as_size_base<T, YA>(allocator, size_), : A(allocator),
data(result) { data(size, result) {
} }
template<class U> template<class U>
as_allocator(const as_allocator<T, R, A, U>& other) as_allocator(const as_allocator<U, T, R>& other)
: as_size_base<T, YA>(other), : A(other.allocator()),
data(other.data) { data(other.data) {
} }
#if !defined(BOOST_NO_CXX11_ALLOCATOR) pointer allocate(size_type count, const_void_pointer hint = 0) {
size_type max_size() const {
return YT::max_size(*this);
}
#else
using YA::address;
using YA::max_size;
#endif
pointer allocate(size_type count, const void* value = 0) {
enum { enum {
M = boost::alignment_of<type>::value M = boost::alignment_of<type>::value
}; };
std::size_t n1 = count * sizeof(value_type); std::size_t n1 = count * sizeof(value_type);
std::size_t n2 = size * sizeof(type) + M - 1; std::size_t n2 = data.size * sizeof(type) + M;
CA ca(*this); CA ca(allocator());
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
void* p1 = CT::allocate(ca, n1 + n2, value); void* p1 = CT::allocate(ca, n1 + n2, hint);
#else #else
void* p1 = ca.allocate(n1 + n2, value); void* p1 = ca.allocate(n1 + n2, hint);
#endif #endif
void* p2 = static_cast<char*>(p1) + n1; void* p2 = static_cast<char*>(p1) + n1;
p2 = sp_align(M, p2); p2 = sp_align(M, p2);
@ -170,51 +148,18 @@ namespace boost {
M = boost::alignment_of<type>::value M = boost::alignment_of<type>::value
}; };
std::size_t n1 = count * sizeof(value_type); std::size_t n1 = count * sizeof(value_type);
std::size_t n2 = size * sizeof(type) + M - 1; std::size_t n2 = data.size * sizeof(type) + M;
char* p1 = reinterpret_cast<char*>(memory); char* p1 = reinterpret_cast<char*>(memory);
CA ca(*this); CA ca(allocator());
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
CT::deallocate(ca, p1, n1 + n2);
#else
ca.deallocate(p1, n1 + n2); ca.deallocate(p1, n1 + n2);
#endif
} }
template<class U> const A& allocator() const {
void construct(U* memory, const_reference value) { return static_cast<const A&>(*this);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::construct(*this, memory, value);
#else
YA::construct(memory, value);
#endif
} }
template<class U> A& allocator() {
void destroy(U* memory) { return static_cast<A&>(*this);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::destroy(*this, memory);
#else
YA::destroy(memory);
#endif
}
#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<class U, class... Args>
void construct(U* memory, Args&&... args) {
YT::construct(*this, memory, std::forward<Args>(args)...);
}
#endif
template<class U>
bool operator==(const as_allocator<T, R, A, U>& other) const {
return true;
}
template<class U>
bool operator!=(const as_allocator<T, R, A, U>& other) const {
return !(*this == other);
} }
void set(type* memory) { void set(type* memory) {
@ -231,44 +176,37 @@ namespace boost {
private: private:
void free(ms_init_tag) { void free(ms_init_tag) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
as_destroy(*this, data.object, size); as_destroy(allocator(), data.object, data.size);
#else #else
ms_destroy(data.object, size); ms_destroy(data.object, data.size);
#endif #endif
} }
void free(ms_noinit_tag) { void free(ms_noinit_tag) {
ms_destroy(data.object, size); ms_destroy(data.object, data.size);
} }
ms_allocator_state<type> data; ms_allocator_state<T> data;
}; };
template<class T> template<class A1, class A2, class T, class R>
struct ms_size_base; bool operator==(const as_allocator<A1, T, R>& a1,
const as_allocator<A2, T, R>& a2) {
return a1.allocator() == a2.allocator();
}
template<class T> template<class A1, class A2, class T, class R>
struct ms_size_base<T[]> { bool operator!=(const as_allocator<A1, T, R>& a1,
ms_size_base(std::size_t size_) const as_allocator<A2, T, R>& a2) {
: size(size_ * array_total<T>::size) { return a1.allocator() != a2.allocator();
} }
std::size_t size; template<class T, class Y = char>
}; class ms_allocator;
template<class T, std::size_t N> template<class T, class Y>
struct ms_size_base<T[N]> { class ms_allocator {
enum { template<class T_, class Y_>
size = array_total<T[N]>::size
};
};
template<class T, class R, class Y = char>
class ms_allocator
: ms_size_base<T> {
using ms_size_base<T>::size;
template<class T_, class R_, class Y_>
friend class ms_allocator; friend class ms_allocator;
public: public:
@ -284,22 +222,38 @@ namespace boost {
template<class U> template<class U>
struct rebind { struct rebind {
typedef ms_allocator<T, R, U> other; typedef ms_allocator<T, U> other;
}; };
ms_allocator(type** result) ms_allocator(type** result)
: data(result) { : data(result) {
} }
ms_allocator(std::size_t size_, type** result) ms_allocator(std::size_t size, type** result)
: ms_size_base<T>(size_), : data(size, result) {
data(result) {
} }
template<class U> template<class U>
ms_allocator(const ms_allocator<T, R, U>& other) ms_allocator(const ms_allocator<T, U>& other)
: ms_size_base<T>(other), : data(other.data) {
data(other.data) { }
pointer allocate(size_type count, const void* = 0) {
enum {
M = boost::alignment_of<type>::value
};
std::size_t n1 = count * sizeof(Y);
std::size_t n2 = data.size * sizeof(type) + M;
void* p1 = ::operator new(n1 + n2);
void* p2 = static_cast<char*>(p1) + n1;
p2 = sp_align(M, p2);
*data.result = static_cast<type*>(p2);
return static_cast<Y*>(p1);
}
void deallocate(pointer memory, size_type) {
void* p1 = memory;
::operator delete(p1);
} }
#if defined(BOOST_NO_CXX11_ALLOCATOR) #if defined(BOOST_NO_CXX11_ALLOCATOR)
@ -310,78 +264,50 @@ namespace boost {
const_pointer address(const_reference value) const { const_pointer address(const_reference value) const {
return &value; return &value;
} }
#endif
size_type max_size() const { size_type max_size() const {
enum { enum {
N = static_cast<std::size_t>(-1) / sizeof(value_type) N = static_cast<std::size_t>(-1) / sizeof(Y)
}; };
return N; return N;
} }
pointer allocate(size_type count, const void* = 0) { void construct(pointer memory, const_reference value) {
enum {
M = boost::alignment_of<type>::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<char*>(p1) + n1;
p2 = sp_align(M, p2);
*data.result = static_cast<type*>(p2);
return static_cast<value_type*>(p1);
}
void deallocate(pointer memory, size_type) {
void* p1 = memory; void* p1 = memory;
::operator delete(p1); ::new(p1) Y(value);
} }
template<class U> void destroy(pointer memory) {
void construct(U* memory, const_reference value) { memory->~Y();
void* p1 = memory;
::new(p1) U(value);
}
template<class U>
void destroy(U* memory) {
memory->~U();
}
#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<class U, class... Args>
void construct(U* memory, Args&&... args) {
void* p1 = memory;
::new(p1) U(std::forward<Args>(args)...);
} }
#endif #endif
template<class U>
bool operator==(const ms_allocator<T, R, U>&) const {
return true;
}
template<class U>
bool operator!=(const ms_allocator<T, R, U>& other) const {
return !(*this == other);
}
void set(type* memory) { void set(type* memory) {
data.object = memory; data.object = memory;
} }
void operator()() { void operator()() {
if (data.object) { if (data.object) {
ms_destroy(data.object, size); ms_destroy(data.object, data.size);
} }
} }
private: private:
ms_allocator_state<type> data; ms_allocator_state<T> data;
}; };
template<class T, class Y1, class Y2>
bool operator==(const ms_allocator<T, Y1>&,
const ms_allocator<T, Y2>&) {
return true;
}
template<class T, class Y1, class Y2>
bool operator!=(const ms_allocator<T, Y1>&,
const ms_allocator<T, Y2>&) {
return false;
}
class ms_in_allocator_tag { class ms_in_allocator_tag {
public: public:
void operator()(const void*) { void operator()(const void*) {

View File

@ -18,8 +18,7 @@ namespace boost {
make_shared(std::size_t size) { make_shared(std::size_t size) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_init_tag R1; typedef boost::detail::ms_allocator<T> A1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
std::size_t n1 = size * boost::detail::array_total<T1>::size; std::size_t n1 = size * boost::detail::array_total<T1>::size;
T1* p1 = 0; T1* p1 = 0;
@ -40,8 +39,7 @@ namespace boost {
make_shared() { make_shared() {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_init_tag R1; typedef boost::detail::ms_allocator<T> A1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
enum { enum {
N = boost::detail::array_total<T>::size N = boost::detail::array_total<T>::size
@ -66,8 +64,7 @@ namespace boost {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3; typedef const T2 T3;
typedef boost::detail::ms_init_tag R1; typedef boost::detail::ms_allocator<T> A1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
enum { enum {
M = boost::detail::array_total<T1>::size M = boost::detail::array_total<T1>::size
@ -93,8 +90,7 @@ namespace boost {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef const T2 T3; typedef const T2 T3;
typedef boost::detail::ms_init_tag R1; typedef boost::detail::ms_allocator<T> A1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
enum { enum {
M = boost::detail::array_total<T1>::size, M = boost::detail::array_total<T1>::size,
@ -119,8 +115,7 @@ namespace boost {
make_shared_noinit(std::size_t size) { make_shared_noinit(std::size_t size) {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_noinit_tag R1; typedef boost::detail::ms_allocator<T> A1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
std::size_t n1 = size * boost::detail::array_total<T1>::size; std::size_t n1 = size * boost::detail::array_total<T1>::size;
T1* p1 = 0; T1* p1 = 0;
@ -141,8 +136,7 @@ namespace boost {
make_shared_noinit() { make_shared_noinit() {
typedef typename boost::detail::array_inner<T>::type T1; typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2; typedef typename boost::detail::array_base<T1>::type T2;
typedef boost::detail::ms_noinit_tag R1; typedef boost::detail::ms_allocator<T> A1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_in_allocator_tag D1; typedef boost::detail::ms_in_allocator_tag D1;
enum { enum {
N = boost::detail::array_total<T>::size N = boost::detail::array_total<T>::size

View File

@ -15,13 +15,6 @@ class creator {
public: public:
typedef T value_type; typedef T value_type;
#if defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
template<typename U>
struct rebind {
typedef creator<U> other;
};
#endif
creator() { creator() {
} }