Spatial optimization for make_shared for arrays

Saves up to sizeof(void*) + sizeof(size_t) bytes for make_shared and saves
sizeof(void*) + sizeof(size_t) + sizeof(A) bytes for allocate_shared where A is the
supplied allocator type.
This commit is contained in:
Glen Fernandes
2014-02-10 20:54:48 -08:00
parent 260af64027
commit 5f485c2952
9 changed files with 460 additions and 465 deletions

View File

@ -9,152 +9,166 @@
#ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
#include <boost/smart_ptr/detail/array_allocator.hpp>
#include <boost/smart_ptr/detail/array_deleter.hpp>
#include <boost/smart_ptr/detail/array_count_impl.hpp>
#include <boost/smart_ptr/detail/sp_if_array.hpp>
#include <boost/type_traits/remove_cv.hpp>
namespace boost {
template<typename T, typename A>
template<class T, class A>
inline typename boost::detail::sp_if_array<T>::type
allocate_shared(const A& allocator, std::size_t size) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef boost::detail::as_allocator<T3[], A> A1;
typedef boost::detail::as_deleter<T3[], A> D1;
T1* p1 = 0;
T3* p2 = 0;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::ms_allocator<T, R1, A> A1;
typedef boost::detail::ms_noop D1;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
D1 d1(allocator, n1);
A1 a1(allocator, n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1);
p1 = reinterpret_cast<T1*>(p2);
T1* p1 = 0;
T2* p2 = 0;
D1 d1;
A1 a1(allocator, size, &p2);
shared_ptr<T> s1(p1, d1, a1);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
boost::detail::as_init(allocator, p2, n1);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
#else
boost::detail::ms_init(p2, n1);
#endif
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
return shared_ptr<T>(s1, p1);
}
template<typename T, typename A>
template<class T, class A>
inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared(const A& allocator) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::ms_allocator<T, R1, A> A1;
typedef boost::detail::ms_noop D1;
enum {
N = boost::detail::array_total<T>::size
};
typedef boost::detail::as_allocator<T3[N], A> A1;
typedef boost::detail::as_deleter<T3[N], A> D1;
T1* p1 = 0;
T3* p2 = 0;
D1 d1(allocator);
T2* p2 = 0;
D1 d1;
A1 a1(allocator, &p2);
boost::shared_ptr<T> s1(p1, d1, a1);
p1 = reinterpret_cast<T1*>(p2);
shared_ptr<T> s1(p1, d1, a1);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
boost::detail::as_init(allocator, p2, N);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
#else
boost::detail::ms_init(p2, N);
#endif
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
return shared_ptr<T>(s1, p1);
}
template<typename T, typename A>
template<class T, class A>
inline typename boost::detail::sp_if_array<T>::type
allocate_shared(const A& allocator, std::size_t size,
const typename boost::detail::array_inner<T>::type& value) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef const T2 T4;
typedef boost::detail::as_allocator<T3[], A> A1;
typedef boost::detail::as_deleter<T3[], A> D1;
typedef const T2 T3;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::ms_allocator<T, R1, A> A1;
typedef boost::detail::ms_noop D1;
enum {
M = boost::detail::array_total<T1>::size
};
T1* p1 = 0;
T3* p2 = 0;
T4* p3 = reinterpret_cast<T4*>(&value);
std::size_t n1 = M * size;
D1 d1(allocator, n1);
A1 a1(allocator, n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1);
T1* p1 = 0;
T2* p2 = 0;
T3* p3 = reinterpret_cast<T3*>(&value);
D1 d1;
A1 a1(allocator, size, &p2);
shared_ptr<T> s1(p1, d1, a1);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
boost::detail::as_init<T2, A, M>(allocator, p2, n1, p3);
#else
boost::detail::ms_init<T2, M>(p2, n1, p3);
#endif
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
boost::detail::as_init<T3, A, M>(allocator, p2, n1, p3);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
return shared_ptr<T>(s1, p1);
}
template<typename T, typename A>
template<class T, class A>
inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared(const A& allocator,
const typename boost::detail::array_inner<T>::type& value) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef const T2 T4;
typedef const T2 T3;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::ms_allocator<T, R1, A> A1;
typedef boost::detail::ms_noop D1;
enum {
M = boost::detail::array_total<T1>::size,
N = boost::detail::array_total<T>::size
N = boost::detail::array_total<T>::size,
M = boost::detail::array_total<T1>::size
};
typedef boost::detail::as_allocator<T3[N], A> A1;
typedef boost::detail::as_deleter<T3[N], A> D1;
T1* p1 = 0;
T3* p2 = 0;
T4* p3 = reinterpret_cast<T4*>(&value);
D1 d1(allocator);
T2* p2 = 0;
T3* p3 = reinterpret_cast<T3*>(&value);
D1 d1;
A1 a1(allocator, &p2);
boost::shared_ptr<T> s1(p1, d1, a1);
shared_ptr<T> s1(p1, d1, a1);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
boost::detail::as_init<T2, A, M>(allocator, p2, N, p3);
#else
boost::detail::as_init<T2, M>(p2, N, p3);
#endif
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
boost::detail::as_init<T3, A, M>(allocator, p2, N, p3);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
return shared_ptr<T>(s1, p1);
}
template<typename T, typename A>
template<class T, class A>
inline typename boost::detail::sp_if_array<T>::type
allocate_shared_noinit(const A& allocator, std::size_t size) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef boost::detail::as_allocator<T3[], A> A1;
typedef boost::detail::ms_deleter<T3[]> D1;
T1* p1 = 0;
T3* p2 = 0;
typedef boost::detail::ms_noinit_tag R1;
typedef boost::detail::ms_allocator<T, R1, A> A1;
typedef boost::detail::ms_noop D1;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
D1 d1(n1);
A1 a1(allocator, n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1);
p1 = reinterpret_cast<T1*>(p2);
T1* p1 = 0;
T2* p2 = 0;
D1 d1;
A1 a1(allocator, size, &p2);
shared_ptr<T> s1(p1, d1, a1);
boost::detail::ms_noinit(p2, n1);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
return shared_ptr<T>(s1, p1);
}
template<typename T, typename A>
template<class T, class A>
inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared_noinit(const A& allocator) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef boost::detail::ms_noinit_tag R1;
typedef boost::detail::ms_allocator<T, R1, A> A1;
typedef boost::detail::ms_noop D1;
enum {
N = boost::detail::array_total<T>::size
};
typedef boost::detail::as_allocator<T3[N], A> A1;
typedef boost::detail::ms_deleter<T3[N]> D1;
T1* p1 = 0;
T3* p2 = 0;
T2* p2 = 0;
D1 d1;
A1 a1(allocator, &p2);
boost::shared_ptr<T> s1(p1, d1, a1);
p1 = reinterpret_cast<T1*>(p2);
shared_ptr<T> s1(p1, d1, a1);
boost::detail::ms_noinit(p2, N);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
return shared_ptr<T>(s1, p1);
}
}

View File

@ -1,29 +0,0 @@
/*
* 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_ALLOCATOR_PAIR_HPP
#define BOOST_SMART_PTR_DETAIL_ALLOCATOR_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

@ -9,8 +9,8 @@
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
#define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP
#include <boost/smart_ptr/detail/allocator_pair.hpp>
#include <boost/smart_ptr/detail/array_traits.hpp>
#include <boost/smart_ptr/detail/array_utility.hpp>
#include <boost/type_traits/alignment_of.hpp>
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
#include <memory>
@ -18,32 +18,42 @@
namespace boost {
namespace detail {
template<typename T>
struct ms_allocator_base;
template<class T, class A>
struct as_size_base;
template<typename T>
struct ms_allocator_base<T[]> {
ms_allocator_base(std::size_t size_)
: size(size_ * sizeof(T)) {
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) {
}
std::size_t size;
};
template<typename T, std::size_t N>
struct ms_allocator_base<T[N]> {
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) {
}
enum {
size = N * sizeof(T)
size = array_total<T[N]>::size
};
};
template<typename T, typename A, typename Y = char>
class as_allocator
: ms_allocator_base<T> {
using ms_allocator_base<T>::size;
struct ms_init_tag { };
struct ms_noinit_tag { };
template<typename T_, typename A_, typename Y_>
friend class as_allocator;
template<class T, class R, class A = void, class Y = char>
class ms_allocator
: as_size_base<T, A> {
using as_size_base<T, A>::size;
template<class T_, class R_, class A_, class Y_>
friend class ms_allocator;
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename std::allocator_traits<A>::
@ -60,7 +70,7 @@ namespace boost {
#endif
public:
typedef typename array_inner<T>::type type;
typedef typename array_base<T>::type type;
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename YT::value_type value_type;
@ -80,52 +90,62 @@ namespace boost {
typedef typename YA::const_reference const_reference;
#endif
template<typename U>
template<class U>
struct rebind {
typedef as_allocator<T, A, U> other;
typedef ms_allocator<T, R, A, U> other;
};
as_allocator(const A& allocator, type** data)
: pair(allocator, data) {
ms_allocator(const A& allocator, type** data_)
: as_size_base<T, A>(allocator),
data(data_),
object(0) {
}
as_allocator(const A& allocator, std::size_t size_, type** data)
: ms_allocator_base<T>(size_),
pair(allocator, data) {
ms_allocator(const A& allocator, std::size_t size_, type** data_)
: as_size_base<T, A>(allocator, size_),
data(data_),
object(0) {
}
template<class U>
as_allocator(const as_allocator<T, A, U>& other)
: ms_allocator_base<T>(other),
pair(other.pair, other.pair.data) {
ms_allocator(const ms_allocator<T, R, A, U>& other)
: as_size_base<T, A>(other),
data(other.data),
object(other.object) {
}
pointer address(reference value) const {
return pair.address(value);
YA ya(*this);
return ya.address(value);
}
const_pointer address(const_reference value) const {
return pair.address(value);
YA ya(*this);
return ya.address(value);
}
size_type max_size() const {
return pair.max_size();
YA ya(*this);
return ya.max_size();
}
pointer allocate(size_type count, const void* value = 0) {
std::size_t a1 = boost::alignment_of<type>::value;
std::size_t n1 = count * sizeof(value_type) + a1 - 1;
CA ca(pair);
enum {
M = boost::alignment_of<type>::value
};
std::size_t n1 = count * sizeof(value_type) + M - 1;
std::size_t n2 = size * sizeof(type);
CA ca(*this);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
char* p1 = CT::allocate(ca, size + n1, value);
char* p1 = CT::allocate(ca, n1 + n2, value);
#else
char* p1 = ca.allocate(size + n1, value);
char* p1 = ca.allocate(n1 + n2, value);
#endif
char* p2 = p1 + n1;
while (std::size_t(p2) % a1 != 0) {
while (std::size_t(p2) % M != 0) {
p2--;
}
*pair.data = reinterpret_cast<type*>(p2);
*data = reinterpret_cast<type*>(p2);
return reinterpret_cast<value_type*>(p1);
}
@ -133,7 +153,7 @@ namespace boost {
std::size_t a1 = boost::alignment_of<type>::value;
std::size_t n1 = count * sizeof(value_type) + a1 - 1;
char* p1 = reinterpret_cast<char*>(memory);
CA ca(pair);
CA ca(*this);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
CT::deallocate(ca, p1, size + n1);
#else
@ -141,58 +161,105 @@ namespace boost {
#endif
}
template<typename U>
template<class U>
void construct(U* memory, const_reference value) {
YA ya(*this);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::construct(pair, memory, value);
YT::construct(ya, memory, value);
#else
pair.construct(memory, value);
ya.construct(memory, value);
#endif
}
template<typename U>
template<class U>
void destroy(U* memory) {
YA ya(*this);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::destroy(pair, memory);
YT::destroy(ya, memory);
#else
pair.destroy(memory);
ya.destroy(memory);
#endif
}
#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<typename U, typename... Args>
template<class U, class... Args>
void construct(U* memory, Args&&... args) {
YT::construct(pair, memory, std::forward<Args>(args)...);
YA ya(*this);
YT::construct(ya, memory, std::forward<Args>(args)...);
}
#endif
template<typename U>
bool operator==(const as_allocator<T, A, U>& other) const {
return pair == other.pair;
template<class U>
bool operator==(const ms_allocator<T, R, A, U>& other) const {
return true;
}
template<typename U>
bool operator!=(const as_allocator<T, A, U>& other) const {
return !(*this == other);
template<class U>
bool operator!=(const ms_allocator<T, R, A, U>& other) const {
return !(*this == other);
}
void set(type* memory) {
object = memory;
}
void operator()() {
if (object) {
R tag;
free(tag);
}
}
private:
as_pair<YA, type**> pair;
void free(ms_init_tag) {
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
const A& a1(*this);
as_destroy(a1, object, size);
#else
ms_destroy(object, size);
#endif
}
void free(ms_noinit_tag) {
ms_destroy(object, size);
}
type** data;
type* object;
};
template<typename T, typename Y = char>
class ms_allocator
: ms_allocator_base<T> {
using ms_allocator_base<T>::size;
template<class T>
struct ms_size_base;
template<typename T_, typename Y_>
template<class T>
struct ms_size_base<T[]> {
ms_size_base(std::size_t size_)
: size(size_ * array_total<T>::size) {
}
std::size_t size;
};
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>
class ms_allocator<T, R, void, Y>
: ms_size_base<T> {
using ms_size_base<T>::size;
template<class T_, class R_, class A_, class Y_>
friend class ms_allocator;
public:
typedef typename array_inner<T>::type type;
typedef typename array_base<T>::type type;
typedef Y value_type;
typedef Y* pointer;
typedef const Y* const_pointer;
@ -201,24 +268,27 @@ namespace boost {
typedef Y& reference;
typedef const Y& const_reference;
template<typename U>
template<class U>
struct rebind {
typedef ms_allocator<T, U> other;
typedef ms_allocator<T, R, void, U> other;
};
ms_allocator(type** data_)
: data(data_) {
: data(data_),
object(0) {
}
ms_allocator(std::size_t size_, type** data_)
: ms_allocator_base<T>(size_),
data(data_) {
: ms_size_base<T>(size_),
data(data_),
object(0) {
}
template<class U>
ms_allocator(const ms_allocator<T, U>& other)
: ms_allocator_base<T>(other),
data(other.data) {
ms_allocator(const ms_allocator<T, R, void, U>& other)
: ms_size_base<T>(other),
data(other.data),
object(other.object) {
}
pointer address(reference value) const {
@ -237,11 +307,14 @@ namespace boost {
}
pointer allocate(size_type count, const void* = 0) {
std::size_t a1 = boost::alignment_of<type>::value;
std::size_t n1 = count * sizeof(value_type) + a1 - 1;
void* p1 = ::operator new(n1 + size);
enum {
M = boost::alignment_of<type>::value
};
std::size_t n1 = count * sizeof(value_type) + M - 1;
std::size_t n2 = size * sizeof(type);
void* p1 = ::operator new(n1 + n2);
char* p2 = static_cast<char*>(p1) + n1;
while (std::size_t(p2) % a1 != 0) {
while (std::size_t(p2) % M != 0) {
p2--;
}
*data = reinterpret_cast<type*>(p2);
@ -253,13 +326,13 @@ namespace boost {
::operator delete(p1);
}
template<typename U>
template<class U>
void construct(U* memory, const_reference value) {
void* p1 = memory;
::new(p1) U(value);
}
template<typename U>
template<class U>
void destroy(U* memory) {
memory->~U();
}
@ -267,25 +340,42 @@ namespace boost {
#if !defined(BOOST_NO_CXX11_ALLOCATOR) && \
!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
!defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
template<typename U, typename... Args>
template<class U, class... Args>
void construct(U* memory, Args&&... args) {
void* p1 = memory;
::new(p1) U(std::forward<Args>(args)...);
}
#endif
template<typename U>
bool operator==(const ms_allocator<T, U>&) const {
template<class U>
bool operator==(const ms_allocator<T, R, void, U>&) const {
return true;
}
template<typename U>
bool operator!=(const ms_allocator<T, U>& other) const {
template<class U>
bool operator!=(const ms_allocator<T, R, void, U>& other) const {
return !(*this == other);
}
void set(type* memory) {
object = memory;
}
void operator()() {
if (object) {
ms_destroy(object, size);
}
}
private:
type** data;
type* object;
};
class ms_noop {
public:
void operator()(const void*) {
}
};
}
}

View File

@ -0,0 +1,68 @@
/*
* 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_ARRAY_COUNT_IMPL_HPP
#define BOOST_SMART_PTR_DETAIL_ARRAY_COUNT_IMPL_HPP
#include <boost/smart_ptr/detail/array_allocator.hpp>
#include <boost/smart_ptr/detail/sp_counted_impl.hpp>
namespace boost {
namespace detail {
template<class P, class T_, class R_, class A_>
class sp_counted_impl_pda<P, ms_noop, ms_allocator<T_, R_, A_> >
: public sp_counted_base {
typedef ms_noop D;
typedef ms_allocator<T_, R_, A_> A;
typedef sp_counted_impl_pda<P, D, A> Y;
public:
sp_counted_impl_pda(const P&, const D&, const A& allocator_)
: allocator(allocator_) {
}
virtual void dispose() {
allocator();
}
virtual void destroy() {
#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_traits<Y> YT;
#else
typedef typename A::template rebind<Y>::other YA;
#endif
YA a1(allocator);
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
YT::destroy(a1, this);
YT::deallocate(a1, this, 1);
#else
this->~Y();
a1.deallocate(this, 1);
#endif
}
virtual void* get_deleter(const sp_typeinfo&) {
return &reinterpret_cast<char&>(allocator);
}
virtual void* get_untyped_deleter() {
return &reinterpret_cast<char&>(allocator);
}
private:
sp_counted_impl_pda(const sp_counted_impl_pda&);
sp_counted_impl_pda& operator=(const sp_counted_impl_pda&);
A allocator;
};
}
}
#endif

View File

@ -1,109 +0,0 @@
/*
* 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)
*/
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP
#define BOOST_SMART_PTR_DETAIL_ARRAY_DELETER_HPP
#include <boost/smart_ptr/detail/allocator_pair.hpp>
#include <boost/smart_ptr/detail/array_traits.hpp>
#include <boost/smart_ptr/detail/array_utility.hpp>
namespace boost {
namespace detail {
template<typename T>
struct ms_deleter_base;
template<typename T>
struct ms_deleter_base<T[]> {
ms_deleter_base(std::size_t size_)
: size(size_) {
}
std::size_t size;
};
template<typename T, std::size_t N>
struct ms_deleter_base<T[N]> {
enum {
size = N
};
};
template<typename T, typename A>
class as_deleter
: ms_deleter_base<T> {
using ms_deleter_base<T>::size;
public:
typedef typename array_inner<T>::type type;
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
typedef typename std::allocator_traits<A>::
template rebind_alloc<type> allocator;
#else
typedef typename A::
template rebind<type>::other allocator;
#endif
as_deleter(const A& allocator_)
: pair(allocator_, 0) {
}
as_deleter(const A& allocator_, std::size_t size_)
: ms_deleter_base<T>(size_),
pair(allocator_, 0) {
}
void set(type* memory) {
pair.data = memory;
}
void operator()(const void*) {
if (pair.data) {
as_destroy<type, allocator>(pair, pair.data, size);
}
}
private:
as_pair<allocator, type*> pair;
};
template<typename T>
class ms_deleter
: ms_deleter_base<T> {
using ms_deleter_base<T>::size;
public:
typedef typename array_inner<T>::type type;
ms_deleter()
: object(0) {
}
ms_deleter(std::size_t size_)
: ms_deleter_base<T>(size_),
object(0) {
}
void set(type* memory) {
object = memory;
}
void operator()(const void*) {
if (object) {
ms_destroy(object, size);
}
}
private:
type* object;
};
}
}
#endif

View File

@ -9,48 +9,48 @@
#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP
#define BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP
#include <cstddef>
#include <boost/type_traits/remove_cv.hpp>
namespace boost {
namespace detail {
template<typename T>
template<class T>
struct array_base {
typedef T type;
typedef typename boost::remove_cv<T>::type type;
};
template<typename T>
template<class T>
struct array_base<T[]> {
typedef typename array_base<T>::type type;
};
template<typename T, std::size_t N>
template<class T, std::size_t N>
struct array_base<T[N]> {
typedef typename array_base<T>::type type;
};
template<typename T>
template<class T>
struct array_total {
enum {
size = 1
};
};
template<typename T, std::size_t N>
template<class T, std::size_t N>
struct array_total<T[N]> {
enum {
size = N * array_total<T>::size
};
};
template<typename T>
template<class T>
struct array_inner;
template<typename T>
template<class T>
struct array_inner<T[]> {
typedef T type;
};
template<typename T, std::size_t N>
template<class T, std::size_t N>
struct array_inner<T[N]> {
typedef T type;
};

View File

@ -21,43 +21,24 @@ namespace boost {
typedef boost::true_type ms_is_trivial;
typedef boost::false_type ms_no_trivial;
template<typename T>
template<class T>
inline void ms_destroy(T*, std::size_t, ms_is_trivial) {
}
template<typename T>
template<class T>
inline void ms_destroy(T* memory, std::size_t size, ms_no_trivial) {
for (std::size_t i = size; i > 0;) {
memory[--i].~T();
}
}
template<typename T>
template<class T>
inline void ms_destroy(T* memory, std::size_t size) {
boost::has_trivial_destructor<T> trivial;
ms_destroy(memory, size, trivial);
}
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<typename T, typename A>
inline void as_destroy(A& allocator, T* memory,
std::size_t size) {
typedef typename std::allocator_traits<A>::
template rebind_traits<T> TT;
for (std::size_t i = size; i > 0;) {
TT::destroy(allocator, &memory[--i]);
}
}
#else
template<typename T, typename A>
inline void as_destroy(const A&, T* memory,
std::size_t size) {
boost::has_trivial_destructor<T> trivial;
ms_destroy(memory, size, trivial);
}
#endif
template<typename T>
template<class T>
inline void ms_init(T* memory, std::size_t size, ms_is_trivial) {
for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i;
@ -65,7 +46,7 @@ namespace boost {
}
}
template<typename T>
template<class T>
inline void ms_init(T* memory, std::size_t size, ms_no_trivial) {
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
@ -86,15 +67,48 @@ namespace boost {
#endif
}
template<typename T>
template<class T>
inline void ms_init(T* memory, std::size_t size) {
boost::has_trivial_default_constructor<T> trivial;
ms_init(memory, size, trivial);
}
template<class T, std::size_t N>
inline void ms_init(T* memory, std::size_t size, const T* list) {
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
try {
for (; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i % N]);
}
} catch (...) {
ms_destroy(memory, i);
throw;
}
#else
for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i % N]);
}
#endif
}
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<typename T, typename A>
template<class T, class A>
inline void as_destroy(const A& allocator, T* memory,
std::size_t size) {
typedef typename std::allocator_traits<A>::
template rebind_alloc<T> TA;
typedef typename std::allocator_traits<A>::
template rebind_traits<T> TT;
TA a2(allocator);
for (std::size_t i = size; i > 0;) {
TT::destroy(a2, &memory[--i]);
}
}
template<class T, class A>
inline void as_init(const A& allocator, T* memory, std::size_t size,
ms_is_trivial) {
typedef typename std::allocator_traits<A>::
@ -107,8 +121,8 @@ namespace boost {
}
}
template<typename T, typename A>
inline void as_init(const A& allocator, T* memory, std::size_t size,
template<class T, class A>
inline void as_init(const A& allocator, T* memory, std::size_t size,
ms_no_trivial) {
typedef typename std::allocator_traits<A>::
template rebind_alloc<T> TA;
@ -132,42 +146,13 @@ namespace boost {
#endif
}
template<typename T, typename A>
template<class T, class A>
inline void as_init(const A& allocator, T* memory, std::size_t size) {
boost::has_trivial_default_constructor<T> trivial;
as_init(allocator, memory, size, trivial);
}
#else
template<typename T, typename A>
inline void as_init(const A&, T* memory, std::size_t size) {
boost::has_trivial_default_constructor<T> trivial;
ms_init(memory, size, trivial);
}
#endif
template<typename T, std::size_t N>
inline void ms_init(T* memory, std::size_t size, const T* list) {
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
try {
for (; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i % N]);
}
} catch (...) {
ms_destroy(memory, i);
throw;
}
#else
for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i % N]);
}
#endif
}
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
template<typename T, typename A, std::size_t N>
template<class T, class A, std::size_t N>
inline void as_init(const A& allocator, T* memory, std::size_t size,
const T* list) {
typedef typename std::allocator_traits<A>::
@ -191,35 +176,13 @@ namespace boost {
}
#endif
}
#else
template<typename T, typename A, std::size_t N>
inline void as_init(const A&, T* memory, std::size_t size,
const T* list) {
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
try {
for (; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i % N]);
}
} catch (...) {
ms_destroy(memory, i);
throw;
}
#else
for (std::size_t i = 0; i < size; i++) {
void* p1 = memory + i;
::new(p1) T(list[i % N]);
}
#endif
}
#endif
template<typename T>
template<class T>
inline void ms_noinit(T*, std::size_t, ms_is_trivial) {
}
template<typename T>
template<class T>
inline void ms_noinit(T* memory, std::size_t size, ms_no_trivial) {
#if !defined(BOOST_NO_EXCEPTIONS)
std::size_t i = 0;
@ -240,7 +203,7 @@ namespace boost {
#endif
}
template<typename T>
template<class T>
inline void ms_noinit(T* memory, std::size_t size) {
boost::has_trivial_default_constructor<T> trivial;
ms_noinit(memory, size, trivial);

View File

@ -13,18 +13,18 @@
namespace boost {
namespace detail {
template<typename T>
template<class T>
struct sp_if_array;
template<typename T>
template<class T>
struct sp_if_array<T[]> {
typedef boost::shared_ptr<T[]> type;
};
template<typename T>
template<class T>
struct sp_if_size_array;
template<typename T, std::size_t N>
template<class T, std::size_t N>
struct sp_if_size_array<T[N]> {
typedef boost::shared_ptr<T[N]> type;
};

View File

@ -9,151 +9,149 @@
#ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
#include <boost/smart_ptr/detail/array_allocator.hpp>
#include <boost/smart_ptr/detail/array_deleter.hpp>
#include <boost/smart_ptr/detail/array_count_impl.hpp>
#include <boost/smart_ptr/detail/sp_if_array.hpp>
#include <boost/type_traits/remove_cv.hpp>
namespace boost {
template<typename T>
template<class T>
inline typename boost::detail::sp_if_array<T>::type
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 typename boost::remove_cv<T2>::type T3;
typedef boost::detail::ms_allocator<T3[]> A1;
typedef boost::detail::ms_deleter<T3[]> D1;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_noop D1;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
T1* p1 = 0;
T3* p2 = 0;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
D1 d1(n1);
T2* p2 = 0;
D1 d1;
A1 a1(n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1);
p1 = reinterpret_cast<T1*>(p2);
shared_ptr<T> s1(p1, d1, a1);
boost::detail::ms_init(p2, n1);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
return shared_ptr<T>(s1, p1);
}
template<typename T>
template<class T>
inline typename boost::detail::sp_if_size_array<T>::type
make_shared() {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_noop D1;
enum {
N = boost::detail::array_total<T>::size
};
typedef boost::detail::ms_allocator<T3[N]> A1;
typedef boost::detail::ms_deleter<T3[N]> D1;
T1* p1 = 0;
T3* p2 = 0;
T2* p2 = 0;
D1 d1;
A1 a1(&p2);
boost::shared_ptr<T> s1(p1, d1, a1);
shared_ptr<T> s1(p1, d1, a1);
p1 = reinterpret_cast<T1*>(p2);
boost::detail::ms_init(p2, N);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
return shared_ptr<T>(s1, p1);
}
template<typename T>
template<class T>
inline typename boost::detail::sp_if_array<T>::type
make_shared(std::size_t size,
const typename boost::detail::array_inner<T>::type& value) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef const T2 T4;
typedef boost::detail::ms_allocator<T3[]> A1;
typedef boost::detail::ms_deleter<T3[]> D1;
typedef const T2 T3;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_noop D1;
enum {
M = boost::detail::array_total<T1>::size
};
T1* p1 = 0;
T3* p2 = 0;
T4* p3 = reinterpret_cast<T4*>(&value);
std::size_t n1 = M * size;
D1 d1(n1);
T1* p1 = 0;
T2* p2 = 0;
T3* p3 = reinterpret_cast<T3*>(&value);
D1 d1;
A1 a1(n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1);
shared_ptr<T> s1(p1, d1, a1);
boost::detail::ms_init<T2, M>(p2, n1, p3);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
boost::detail::ms_init<T3, M>(p2, n1, p3);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
return shared_ptr<T>(s1, p1);
}
template<typename T>
template<class T>
inline typename boost::detail::sp_if_size_array<T>::type
make_shared(const typename boost::detail::array_inner<T>::type& value) {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef const T2 T4;
typedef const T2 T3;
typedef boost::detail::ms_init_tag R1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_noop D1;
enum {
M = boost::detail::array_total<T1>::size,
N = boost::detail::array_total<T>::size
};
typedef boost::detail::ms_allocator<T3[N]> A1;
typedef boost::detail::ms_deleter<T3[N]> D1;
};
T1* p1 = 0;
T3* p2 = 0;
T4* p3 = reinterpret_cast<T4*>(&value);
T2* p2 = 0;
T3* p3 = reinterpret_cast<T3*>(&value);
D1 d1;
A1 a1(&p2);
boost::shared_ptr<T> s1(p1, d1, a1);
shared_ptr<T> s1(p1, d1, a1);
boost::detail::ms_init<T2, M>(p2, N, p3);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
p1 = reinterpret_cast<T1*>(p2);
boost::detail::ms_init<T3, M>(p2, N, p3);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
return shared_ptr<T>(s1, p1);
}
template<typename T>
template<class T>
inline typename boost::detail::sp_if_array<T>::type
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 typename boost::remove_cv<T2>::type T3;
typedef boost::detail::ms_allocator<T3[]> A1;
typedef boost::detail::ms_deleter<T3[]> D1;
typedef boost::detail::ms_noinit_tag R1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_noop D1;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
T1* p1 = 0;
T3* p2 = 0;
std::size_t n1 = size * boost::detail::array_total<T1>::size;
D1 d1(n1);
T2* p2 = 0;
D1 d1;
A1 a1(n1, &p2);
boost::shared_ptr<T> s1(p1, d1, a1);
shared_ptr<T> s1(p1, d1, a1);
p1 = reinterpret_cast<T1*>(p2);
boost::detail::ms_noinit(p2, n1);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
return shared_ptr<T>(s1, p1);
}
template<typename T>
template<class T>
inline typename boost::detail::sp_if_size_array<T>::type
make_shared_noinit() {
typedef typename boost::detail::array_inner<T>::type T1;
typedef typename boost::detail::array_base<T1>::type T2;
typedef typename boost::remove_cv<T2>::type T3;
typedef boost::detail::ms_noinit_tag R1;
typedef boost::detail::ms_allocator<T, R1> A1;
typedef boost::detail::ms_noop D1;
enum {
N = boost::detail::array_total<T>::size
};
typedef boost::detail::ms_allocator<T3[N]> A1;
typedef boost::detail::ms_deleter<T3[N]> D1;
T1* p1 = 0;
T3* p2 = 0;
T2* p2 = 0;
D1 d1;
A1 a1(&p2);
boost::shared_ptr<T> s1(p1, d1, a1);
shared_ptr<T> s1(p1, d1, a1);
p1 = reinterpret_cast<T1*>(p2);
boost::detail::ms_noinit(p2, N);
D1* d2 = static_cast<D1*>(s1._internal_get_untyped_deleter());
d2->set(p2);
return boost::shared_ptr<T>(s1, p1);
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
a2->set(p2);
return shared_ptr<T>(s1, p1);
}
}