Merge commit

This commit is contained in:
Peter Dimov
2014-02-05 00:32:36 +02:00
4 changed files with 230 additions and 55 deletions

View File

@@ -10,6 +10,7 @@
#define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP #define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
#include <boost/smart_ptr/detail/array_traits.hpp> #include <boost/smart_ptr/detail/array_traits.hpp>
#include <boost/smart_ptr/detail/as_pair.hpp>
#include <boost/type_traits/alignment_of.hpp> #include <boost/type_traits/alignment_of.hpp>
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
#include <memory> #include <memory>
@@ -54,8 +55,10 @@ namespace boost {
typedef typename std::allocator_traits<A>:: typedef typename std::allocator_traits<A>::
template rebind_traits<char> CT; template rebind_traits<char> CT;
#else #else
typedef typename A::template rebind<Y>::other YA; typedef typename A::
typedef typename A::template rebind<char>::other CA; template rebind<Y>::other YA;
typedef typename A::
template rebind<char>::other CA;
#endif #endif
public: public:
@@ -84,40 +87,37 @@ namespace boost {
typedef as_allocator<T, A, U> other; typedef as_allocator<T, A, U> other;
}; };
as_allocator(const A& allocator_, type** data_) as_allocator(const A& allocator, type** data)
: allocator(allocator_), : pair(allocator, data) {
data(data_) {
} }
as_allocator(const A& allocator_, std::size_t size_, type** data_) as_allocator(const A& allocator, std::size_t size_, type** data)
: ms_allocator_base<T>(size_), : ms_allocator_base<T>(size_),
allocator(allocator_), pair(allocator, data) {
data(data_) {
} }
template<class U> template<class U>
as_allocator(const as_allocator<T, A, U>& other) as_allocator(const as_allocator<T, A, U>& other)
: ms_allocator_base<T>(other), : ms_allocator_base<T>(other),
allocator(other.allocator), pair(other.pair, other.pair.data) {
data(other.data) {
} }
pointer address(reference value) const { pointer address(reference value) const {
return allocator.address(value); return pair.address(value);
} }
const_pointer address(const_reference value) const { const_pointer address(const_reference value) const {
return allocator.address(value); return pair.address(value);
} }
size_type max_size() const { size_type max_size() const {
return allocator.max_size(); return pair.max_size();
} }
pointer allocate(size_type count, const void* value = 0) { pointer allocate(size_type count, const void* value = 0) {
std::size_t a1 = boost::alignment_of<type>::value; std::size_t a1 = boost::alignment_of<type>::value;
std::size_t n1 = count * sizeof(Y) + a1 - 1; std::size_t n1 = count * sizeof(Y) + a1 - 1;
CA ca(allocator); CA ca(pair);
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
char* p1 = CT::allocate(ca, size + n1, value); char* p1 = CT::allocate(ca, size + n1, value);
#else #else
@@ -127,7 +127,7 @@ namespace boost {
while (std::size_t(p2) % a1 != 0) { while (std::size_t(p2) % a1 != 0) {
p2--; p2--;
} }
*data = reinterpret_cast<type*>(p2); *pair.data = reinterpret_cast<type*>(p2);
return reinterpret_cast<Y*>(p1); return reinterpret_cast<Y*>(p1);
} }
@@ -135,7 +135,7 @@ namespace boost {
std::size_t a1 = boost::alignment_of<type>::value; std::size_t a1 = boost::alignment_of<type>::value;
std::size_t n1 = count * sizeof(Y) + a1 - 1; std::size_t n1 = count * sizeof(Y) + a1 - 1;
char* p1 = reinterpret_cast<char*>(memory); char* p1 = reinterpret_cast<char*>(memory);
CA ca(allocator); CA ca(pair);
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
CT::deallocate(ca, p1, size + n1); CT::deallocate(ca, p1, size + n1);
#else #else
@@ -145,23 +145,23 @@ namespace boost {
void construct(pointer memory, const Y& value) { void construct(pointer memory, const Y& value) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::construct(allocator, memory, value); YT::construct(pair, memory, value);
#else #else
allocator.construct(memory, value); pair.construct(memory, value);
#endif #endif
} }
void destroy(pointer memory) { void destroy(pointer memory) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::destroy(allocator, memory); YT::destroy(pair, memory);
#else #else
allocator.destroy(memory); pair.destroy(memory);
#endif #endif
} }
template<typename U> template<typename U>
bool operator==(const as_allocator<T, A, U>& other) const { bool operator==(const as_allocator<T, A, U>& other) const {
return allocator == other.allocator; return pair == other.pair;
} }
template<typename U> template<typename U>
@@ -170,8 +170,7 @@ namespace boost {
} }
private: private:
YA allocator; as_pair<YA, type**> pair;
type** data;
}; };
template<typename T, typename Y = char> template<typename T, typename Y = char>

View File

@@ -11,6 +11,7 @@
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/smart_ptr/detail/array_traits.hpp> #include <boost/smart_ptr/detail/array_traits.hpp>
#include <boost/smart_ptr/detail/as_pair.hpp>
#include <boost/type_traits/has_trivial_constructor.hpp> #include <boost/type_traits/has_trivial_constructor.hpp>
#include <boost/type_traits/has_trivial_destructor.hpp> #include <boost/type_traits/has_trivial_destructor.hpp>
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
@@ -46,53 +47,42 @@ namespace boost {
public: public:
typedef typename array_inner<T>::type type; typedef typename array_inner<T>::type type;
#if !defined(BOOST_NO_CXX11_ALLOCATOR) as_deleter(const A& allocator)
as_deleter(const A& allocator_) : pair(allocator, 0) {
: allocator(allocator_),
object(0) {
} }
#else
as_deleter(const A&)
: object(0) {
}
#endif
#if !defined(BOOST_NO_CXX11_ALLOCATOR) as_deleter(const A& allocator, std::size_t size_)
as_deleter(const A& allocator_, std::size_t size_)
: ms_deleter_base<T>(size_), : ms_deleter_base<T>(size_),
allocator(allocator_), pair(allocator, 0) {
object(0) {
} }
#else
as_deleter(const A&, std::size_t size_)
: ms_deleter_base<T>(size_),
object(0) {
}
#endif
void init(type* memory) { void init(type* memory) {
value_init(memory); value_init(memory);
object = memory; pair.data = memory;
} }
template<std::size_t N> template<std::size_t N>
void init(type* memory, const type* value) { void init(type* memory, const type* value) {
value_init<N>(memory, value); value_init<N>(memory, value);
object = memory; pair.data = memory;
} }
void operator()(const void*) { void operator()(const void*) {
if (object) { if (pair.data) {
destroy(object, size); destroy(pair.data, size);
} }
} }
private: private:
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename std::allocator_traits<A>:: typedef typename std::allocator_traits<A>::
template rebind_alloc<type> TA; template rebind_alloc<type> TA;
typedef typename std::allocator_traits<A>:: typedef typename std::allocator_traits<A>::
template rebind_traits<type> TT; template rebind_traits<type> TT;
#else
typedef typename A::
template rebind<type>::other TA;
#endif #endif
void destroy(type*, std::size_t, boost::true_type) { void destroy(type*, std::size_t, boost::true_type) {
@@ -101,7 +91,7 @@ namespace boost {
void destroy(type* memory, std::size_t n, boost::false_type) { void destroy(type* memory, std::size_t n, boost::false_type) {
for (std::size_t i = n; i > 0;) { for (std::size_t i = n; i > 0;) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
TT::destroy(allocator, &memory[--i]); TT::destroy(pair, &memory[--i]);
#else #else
memory[--i].~type(); memory[--i].~type();
#endif #endif
@@ -116,7 +106,7 @@ namespace boost {
void value_init(type* memory, boost::true_type) { void value_init(type* memory, boost::true_type) {
for (std::size_t i = 0; i < size; i++) { for (std::size_t i = 0; i < size; i++) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
TT::construct(allocator, memory + i); TT::construct(pair, memory + i);
#else #else
void* p1 = memory + i; void* p1 = memory + i;
::new(p1) type(); ::new(p1) type();
@@ -130,7 +120,7 @@ namespace boost {
try { try {
for (; i < size; i++) { for (; i < size; i++) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
TT::construct(allocator, memory + i); TT::construct(pair, memory + i);
#else #else
void* p1 = memory + i; void* p1 = memory + i;
::new(p1) type(); ::new(p1) type();
@@ -143,7 +133,7 @@ namespace boost {
#else #else
for (std::size_t i = 0; i < size; i++) { for (std::size_t i = 0; i < size; i++) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
TT::construct(allocator, memory + i); TT::construct(pair, memory + i);
#else #else
void* p1 = memory + i; void* p1 = memory + i;
::new(p1) type(); ::new(p1) type();
@@ -164,7 +154,7 @@ namespace boost {
try { try {
for (; i < size; i++) { for (; i < size; i++) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_CXX11_ALLOCATOR)
TT::construct(allocator, memory + i, list[i % N]); TT::construct(pair, memory + i, list[i % N]);
#else #else
void* p1 = memory + i; void* p1 = memory + i;
::new(p1) type(list[i % N]); ::new(p1) type(list[i % N]);
@@ -186,10 +176,7 @@ namespace boost {
#endif #endif
} }
#if !defined(BOOST_NO_CXX11_ALLOCATOR) as_pair<TA, type*> pair;
TA allocator;
#endif
type* object;
}; };
template<typename T> template<typename T>

View File

@@ -0,0 +1,29 @@
/*
* 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_AS_PAIR_HPP
#define BOOST_SMART_PTR_DETAIL_AS_PAIR_HPP
#include <cstddef>
namespace boost {
namespace detail {
template<typename A, typename T>
struct as_pair
: A {
as_pair(const A& allocator, const T& value)
: A(allocator),
data(value) {
}
T data;
};
}
}
#endif

View File

@@ -0,0 +1,160 @@
/*
* 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)
*/
#include <boost/detail/lightweight_test.hpp>
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
#include <boost/smart_ptr/allocate_shared_array.hpp>
template<typename T>
class creator {
public:
typedef T value_type;
creator() {
}
template<typename U>
creator(const creator<U>&) {
}
T* allocate(std::size_t size) {
void* p1 = ::operator new(size * sizeof(T));
return static_cast<T*>(p1);
}
void deallocate(T* memory, std::size_t) {
void* p1 = memory;
::operator delete(p1);
}
template<typename U, typename... Args>
void construct(U* memory, Args&&... args) {
void* p1 = memory;
::new(p1) U(std::forward<Args>(args)...);
}
template<typename U>
void destroy(U* memory) {
memory->~U();
}
};
class type {
friend class creator<type>;
public:
static unsigned int instances;
static type object;
protected:
explicit type() {
instances++;
}
type(const type&) {
instances++;
}
~type() {
instances--;
}
};
unsigned int type::instances;
type type::object;
int main() {
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<type[]> a1 = boost::allocate_shared<type[]>(creator<void>(), 3);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<type[3]> a1 = boost::allocate_shared<type[3]>(creator<void>());
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<type[][2]> a1 = boost::allocate_shared<type[][2]>(creator<void>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 5);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<type[2][2]> a1 = boost::allocate_shared<type[2][2]>(creator<void>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 5);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<const type[]> a1 = boost::allocate_shared<const type[]>(creator<void>(), 3);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<const type[3]> a1 = boost::allocate_shared<const type[3]>(creator<void>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 4);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<const type[][2]> a1 = boost::allocate_shared<const type[][2]>(creator<void>(), 2);
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 5);
a1.reset();
BOOST_TEST(type::instances == 1);
}
BOOST_TEST(type::instances == 1);
{
boost::shared_ptr<const type[2][2]> a1 = boost::allocate_shared<const type[2][2]>(creator<void>());
BOOST_TEST(a1.get() != 0);
BOOST_TEST(a1.use_count() == 1);
BOOST_TEST(type::instances == 5);
a1.reset();
BOOST_TEST(type::instances == 1);
}
return boost::report_errors();
}
#else
int main() {
return 0;
}
#endif