forked from boostorg/smart_ptr
Merge commit
This commit is contained in:
@@ -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>
|
||||||
|
@@ -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>
|
||||||
|
29
include/boost/smart_ptr/detail/as_pair.hpp
Normal file
29
include/boost/smart_ptr/detail/as_pair.hpp
Normal 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
|
160
test/allocate_shared_array_construct_test.cpp
Normal file
160
test/allocate_shared_array_construct_test.cpp
Normal 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
|
Reference in New Issue
Block a user