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

View File

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

View File

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