forked from boostorg/smart_ptr
Merge branch 'develop'
This commit is contained in:
@ -9,152 +9,172 @@
|
||||
#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::as_allocator<T, R1, A> A1;
|
||||
typedef boost::detail::ms_in_allocator_tag 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);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
#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
|
||||
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::as_allocator<T, R1, A> A1;
|
||||
typedef boost::detail::ms_in_allocator_tag 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);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
#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
|
||||
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::as_allocator<T, R1, A> A1;
|
||||
typedef boost::detail::ms_in_allocator_tag 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);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
#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
|
||||
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::as_allocator<T, R1, A> A1;
|
||||
typedef boost::detail::ms_in_allocator_tag 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);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
boost::detail::as_init<T2, A, M>(allocator, p2, N, p3);
|
||||
#else
|
||||
boost::detail::ms_init<T2, M>(p2, N, p3);
|
||||
#endif
|
||||
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::as_allocator<T, R1, A> A1;
|
||||
typedef boost::detail::ms_in_allocator_tag 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);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
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);
|
||||
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::as_allocator<T, R1, A> A1;
|
||||
typedef boost::detail::ms_in_allocator_tag 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);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
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);
|
||||
a2->set(p2);
|
||||
p1 = reinterpret_cast<T1*>(p2);
|
||||
return shared_ptr<T>(s1, p1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -9,40 +9,74 @@
|
||||
#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/smart_ptr/detail/sp_align.hpp>
|
||||
#include <boost/type_traits/alignment_of.hpp>
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
#include <memory>
|
||||
#endif
|
||||
#include <algorithm>
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
template<class U>
|
||||
as_size_base(const as_size_base<T[], U>& other)
|
||||
: A(other),
|
||||
size(other.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) {
|
||||
}
|
||||
|
||||
template<class U>
|
||||
as_size_base(const as_size_base<T[N], U>& other)
|
||||
: A(other) {
|
||||
}
|
||||
|
||||
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_>
|
||||
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
|
||||
#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_>
|
||||
friend class as_allocator;
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
@ -59,8 +93,10 @@ namespace boost {
|
||||
typedef typename A::template rebind<char>::other CA;
|
||||
#endif
|
||||
|
||||
using as_size_base<T, YA>::size;
|
||||
|
||||
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,119 +116,164 @@ 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 as_allocator<T, R, A, U> other;
|
||||
};
|
||||
|
||||
as_allocator(const A& allocator, type** data)
|
||||
: pair(allocator, data) {
|
||||
as_allocator(const A& allocator, type** result)
|
||||
: as_size_base<T, YA>(allocator),
|
||||
data(result) {
|
||||
}
|
||||
|
||||
as_allocator(const A& allocator, std::size_t size_, type** data)
|
||||
: ms_allocator_base<T>(size_),
|
||||
pair(allocator, data) {
|
||||
as_allocator(const A& allocator, std::size_t size_,
|
||||
type** result)
|
||||
: as_size_base<T, YA>(allocator, size_),
|
||||
data(result) {
|
||||
}
|
||||
|
||||
template<class U>
|
||||
as_allocator(const as_allocator<T, A, U>& other)
|
||||
: ms_allocator_base<T>(other),
|
||||
pair(other.pair, other.pair.data) {
|
||||
}
|
||||
|
||||
pointer address(reference value) const {
|
||||
return pair.address(value);
|
||||
}
|
||||
|
||||
const_pointer address(const_reference value) const {
|
||||
return pair.address(value);
|
||||
as_allocator(const as_allocator<T, R, A, U>& other)
|
||||
: as_size_base<T, YA>(other),
|
||||
data(other.data) {
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
size_type max_size() const {
|
||||
return pair.max_size();
|
||||
return YT::max_size(*this);
|
||||
}
|
||||
#else
|
||||
using YA::address;
|
||||
using YA::max_size;
|
||||
#endif
|
||||
|
||||
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);
|
||||
std::size_t n2 = size * sizeof(type) + M - 1;
|
||||
CA ca(*this);
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
char* p1 = CT::allocate(ca, size + n1, value);
|
||||
void* p1 = CT::allocate(ca, n1 + n2, value);
|
||||
#else
|
||||
char* p1 = ca.allocate(size + n1, value);
|
||||
void* p1 = ca.allocate(n1 + n2, value);
|
||||
#endif
|
||||
char* p2 = p1 + n1;
|
||||
while (std::size_t(p2) % a1 != 0) {
|
||||
p2--;
|
||||
}
|
||||
*pair.data = reinterpret_cast<type*>(p2);
|
||||
return reinterpret_cast<value_type*>(p1);
|
||||
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 count) {
|
||||
std::size_t a1 = boost::alignment_of<type>::value;
|
||||
std::size_t n1 = count * sizeof(value_type) + a1 - 1;
|
||||
enum {
|
||||
M = boost::alignment_of<type>::value
|
||||
};
|
||||
std::size_t n1 = count * sizeof(value_type);
|
||||
std::size_t n2 = size * sizeof(type) + M - 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);
|
||||
CT::deallocate(ca, p1, n1 + n2);
|
||||
#else
|
||||
ca.deallocate(p1, size + n1);
|
||||
ca.deallocate(p1, n1 + n2);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
template<class U>
|
||||
void construct(U* memory, const_reference value) {
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
YT::construct(pair, memory, value);
|
||||
|
||||
YT::construct(*this, memory, value);
|
||||
#else
|
||||
pair.construct(memory, value);
|
||||
YA::construct(memory, value);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
template<class U>
|
||||
void destroy(U* memory) {
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
YT::destroy(pair, memory);
|
||||
YT::destroy(*this, 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)...);
|
||||
YT::construct(*this, 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 as_allocator<T, R, A, U>& other) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
bool operator!=(const as_allocator<T, A, U>& other) const {
|
||||
template<class U>
|
||||
bool operator!=(const as_allocator<T, R, A, U>& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
void set(type* memory) {
|
||||
data.object = memory;
|
||||
}
|
||||
|
||||
void operator()() {
|
||||
if (data.object) {
|
||||
R tag;
|
||||
free(tag);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
as_pair<YA, type**> pair;
|
||||
void free(ms_init_tag) {
|
||||
#if !defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
as_destroy(*this, data.object, size);
|
||||
#else
|
||||
ms_destroy(data.object, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void free(ms_noinit_tag) {
|
||||
ms_destroy(data.object, size);
|
||||
}
|
||||
|
||||
ms_allocator_state<type> data;
|
||||
};
|
||||
|
||||
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 = 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;
|
||||
|
||||
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,26 +282,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, U> other;
|
||||
};
|
||||
|
||||
ms_allocator(type** data_)
|
||||
: data(data_) {
|
||||
ms_allocator(type** result)
|
||||
: data(result) {
|
||||
}
|
||||
|
||||
ms_allocator(std::size_t size_, type** data_)
|
||||
: ms_allocator_base<T>(size_),
|
||||
data(data_) {
|
||||
ms_allocator(std::size_t size_, type** result)
|
||||
: ms_size_base<T>(size_),
|
||||
data(result) {
|
||||
}
|
||||
|
||||
template<class U>
|
||||
ms_allocator(const ms_allocator<T, U>& other)
|
||||
: ms_allocator_base<T>(other),
|
||||
ms_allocator(const ms_allocator<T, R, U>& other)
|
||||
: ms_size_base<T>(other),
|
||||
data(other.data) {
|
||||
}
|
||||
|
||||
#if defined(BOOST_NO_CXX11_ALLOCATOR)
|
||||
pointer address(reference value) const {
|
||||
return &value;
|
||||
}
|
||||
@ -228,6 +310,7 @@ namespace boost {
|
||||
const_pointer address(const_reference value) const {
|
||||
return &value;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_type max_size() const {
|
||||
enum {
|
||||
@ -237,15 +320,16 @@ 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);
|
||||
char* p2 = static_cast<char*>(p1) + n1;
|
||||
while (std::size_t(p2) % a1 != 0) {
|
||||
p2--;
|
||||
}
|
||||
*data = reinterpret_cast<type*>(p2);
|
||||
return reinterpret_cast<value_type*>(p1);
|
||||
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) {
|
||||
@ -253,13 +337,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 +351,41 @@ 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, 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, U>& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
void set(type* memory) {
|
||||
data.object = memory;
|
||||
}
|
||||
|
||||
void operator()() {
|
||||
if (data.object) {
|
||||
ms_destroy(data.object, size);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
type** data;
|
||||
ms_allocator_state<type> data;
|
||||
};
|
||||
|
||||
class ms_in_allocator_tag {
|
||||
public:
|
||||
void operator()(const void*) {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
67
include/boost/smart_ptr/detail/array_count_impl.hpp
Normal file
67
include/boost/smart_ptr/detail/array_count_impl.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 A>
|
||||
class sp_counted_impl_pda<P, ms_in_allocator_tag, A>
|
||||
: public sp_counted_base {
|
||||
typedef ms_in_allocator_tag D;
|
||||
typedef sp_counted_impl_pda<P, D, A> Y;
|
||||
public:
|
||||
sp_counted_impl_pda(P, 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
|
@ -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
|
@ -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;
|
||||
};
|
||||
|
@ -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,7 +121,7 @@ namespace boost {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename A>
|
||||
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>::
|
||||
@ -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);
|
||||
|
26
include/boost/smart_ptr/detail/sp_align.hpp
Normal file
26
include/boost/smart_ptr/detail/sp_align.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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_SP_ALIGN_HPP
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_ALIGN_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
inline void* sp_align(std::size_t alignment, void* ptr) {
|
||||
std::size_t n1 = (std::size_t)ptr % alignment;
|
||||
if (n1 != 0) {
|
||||
ptr = (char*)ptr + alignment - n1;
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -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;
|
||||
};
|
||||
|
152
include/boost/smart_ptr/detail/sp_interlocked.hpp
Normal file
152
include/boost/smart_ptr/detail/sp_interlocked.hpp
Normal file
@ -0,0 +1,152 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_INTERLOCKED_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SP_INTERLOCKED_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/detail/sp_interlocked.hpp
|
||||
//
|
||||
// Copyright 2005, 2014 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
// BOOST_SP_HAS_INTRIN_H
|
||||
|
||||
// VC9 has intrin.h, but it collides with <utility>
|
||||
#if defined( BOOST_MSVC ) && BOOST_MSVC >= 1600
|
||||
|
||||
# define BOOST_SP_HAS_INTRIN_H
|
||||
|
||||
// Unlike __MINGW64__, __MINGW64_VERSION_MAJOR is defined by MinGW-w64 for both 32 and 64-bit targets.
|
||||
#elif defined( __MINGW64_VERSION_MAJOR )
|
||||
|
||||
// MinGW-w64 provides intrin.h for both 32 and 64-bit targets.
|
||||
# define BOOST_SP_HAS_INTRIN_H
|
||||
|
||||
// Intel C++ on Windows on VC10+ stdlib
|
||||
#elif defined( BOOST_INTEL_WIN ) && defined( _CPPLIB_VER ) && _CPPLIB_VER >= 520
|
||||
|
||||
# define BOOST_SP_HAS_INTRIN_H
|
||||
|
||||
#endif
|
||||
|
||||
#if defined( BOOST_USE_WINDOWS_H )
|
||||
|
||||
# include <windows.h>
|
||||
|
||||
# define BOOST_SP_INTERLOCKED_INCREMENT InterlockedIncrement
|
||||
# define BOOST_SP_INTERLOCKED_DECREMENT InterlockedDecrement
|
||||
# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE InterlockedExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd
|
||||
|
||||
#elif defined( BOOST_USE_INTRIN_H ) || defined( BOOST_SP_HAS_INTRIN_H )
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
# define BOOST_SP_INTERLOCKED_INCREMENT _InterlockedIncrement
|
||||
# define BOOST_SP_INTERLOCKED_DECREMENT _InterlockedDecrement
|
||||
# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE _InterlockedExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd
|
||||
|
||||
#elif defined( _WIN32_WCE )
|
||||
|
||||
#if _WIN32_WCE >= 0x600
|
||||
|
||||
extern "C" long __cdecl _InterlockedIncrement( long volatile * );
|
||||
extern "C" long __cdecl _InterlockedDecrement( long volatile * );
|
||||
extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long );
|
||||
extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
|
||||
extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long );
|
||||
|
||||
# define BOOST_SP_INTERLOCKED_INCREMENT _InterlockedIncrement
|
||||
# define BOOST_SP_INTERLOCKED_DECREMENT _InterlockedDecrement
|
||||
# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE _InterlockedExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd
|
||||
|
||||
#else
|
||||
|
||||
// under Windows CE we still have old-style Interlocked* functions
|
||||
|
||||
extern "C" long __cdecl InterlockedIncrement( long* );
|
||||
extern "C" long __cdecl InterlockedDecrement( long* );
|
||||
extern "C" long __cdecl InterlockedCompareExchange( long*, long, long );
|
||||
extern "C" long __cdecl InterlockedExchange( long*, long );
|
||||
extern "C" long __cdecl InterlockedExchangeAdd( long*, long );
|
||||
|
||||
# define BOOST_SP_INTERLOCKED_INCREMENT InterlockedIncrement
|
||||
# define BOOST_SP_INTERLOCKED_DECREMENT InterlockedDecrement
|
||||
# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE InterlockedCompareExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE InterlockedExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD InterlockedExchangeAdd
|
||||
|
||||
#endif
|
||||
|
||||
#elif defined( BOOST_MSVC ) || defined( BOOST_INTEL_WIN )
|
||||
|
||||
#if defined( __CLRCALL_PURE_OR_CDECL )
|
||||
|
||||
extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedIncrement( long volatile * );
|
||||
extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedDecrement( long volatile * );
|
||||
extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedCompareExchange( long volatile *, long, long );
|
||||
extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedExchange( long volatile *, long );
|
||||
extern "C" long __CLRCALL_PURE_OR_CDECL _InterlockedExchangeAdd( long volatile *, long );
|
||||
|
||||
#else
|
||||
|
||||
extern "C" long __cdecl _InterlockedIncrement( long volatile * );
|
||||
extern "C" long __cdecl _InterlockedDecrement( long volatile * );
|
||||
extern "C" long __cdecl _InterlockedCompareExchange( long volatile *, long, long );
|
||||
extern "C" long __cdecl _InterlockedExchange( long volatile *, long );
|
||||
extern "C" long __cdecl _InterlockedExchangeAdd( long volatile *, long );
|
||||
|
||||
#endif
|
||||
|
||||
# define BOOST_SP_INTERLOCKED_INCREMENT _InterlockedIncrement
|
||||
# define BOOST_SP_INTERLOCKED_DECREMENT _InterlockedDecrement
|
||||
# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE _InterlockedExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD _InterlockedExchangeAdd
|
||||
|
||||
#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedIncrement( long volatile * );
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedDecrement( long volatile * );
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedCompareExchange( long volatile *, long, long );
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedExchange( long volatile *, long );
|
||||
extern "C" __declspec(dllimport) long __stdcall InterlockedExchangeAdd( long volatile *, long );
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
# define BOOST_SP_INTERLOCKED_INCREMENT ::boost::detail::InterlockedIncrement
|
||||
# define BOOST_SP_INTERLOCKED_DECREMENT ::boost::detail::InterlockedDecrement
|
||||
# define BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE ::boost::detail::InterlockedCompareExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE ::boost::detail::InterlockedExchange
|
||||
# define BOOST_SP_INTERLOCKED_EXCHANGE_ADD ::boost::detail::InterlockedExchangeAdd
|
||||
|
||||
#else
|
||||
|
||||
# error "Interlocked intrinsics not available"
|
||||
|
||||
#endif
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_INTERLOCKED_HPP_INCLUDED
|
@ -31,7 +31,10 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/smart_ptr/detail/sp_has_sync.hpp>
|
||||
|
||||
#if defined( BOOST_SP_USE_PTHREADS )
|
||||
#if defined( BOOST_SP_USE_STD_ATOMIC )
|
||||
# include <boost/smart_ptr/detail/spinlock_std_atomic.hpp>
|
||||
|
||||
#elif defined( BOOST_SP_USE_PTHREADS )
|
||||
# include <boost/smart_ptr/detail/spinlock_pt.hpp>
|
||||
|
||||
#elif defined(__GNUC__) && defined( __arm__ ) && !defined( __thumb__ )
|
||||
|
83
include/boost/smart_ptr/detail/spinlock_std_atomic.hpp
Normal file
83
include/boost/smart_ptr/detail/spinlock_std_atomic.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED
|
||||
#define BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// Copyright (c) 2014 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#include <boost/smart_ptr/detail/yield_k.hpp>
|
||||
#include <atomic>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class spinlock
|
||||
{
|
||||
public:
|
||||
|
||||
std::atomic_flag v_;
|
||||
|
||||
public:
|
||||
|
||||
bool try_lock()
|
||||
{
|
||||
return !v_.test_and_set( std::memory_order_acquire );
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
for( unsigned k = 0; !try_lock(); ++k )
|
||||
{
|
||||
boost::detail::yield( k );
|
||||
}
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
v_ .clear( std::memory_order_release );
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
class scoped_lock
|
||||
{
|
||||
private:
|
||||
|
||||
spinlock & sp_;
|
||||
|
||||
scoped_lock( scoped_lock const & );
|
||||
scoped_lock & operator=( scoped_lock const & );
|
||||
|
||||
public:
|
||||
|
||||
explicit scoped_lock( spinlock & sp ): sp_( sp )
|
||||
{
|
||||
sp.lock();
|
||||
}
|
||||
|
||||
~scoped_lock()
|
||||
{
|
||||
sp_.unlock();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
#define BOOST_DETAIL_SPINLOCK_INIT { ATOMIC_FLAG_INIT }
|
||||
|
||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SPINLOCK_STD_ATOMIC_HPP_INCLUDED
|
@ -13,10 +13,10 @@
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
template<class T>
|
||||
struct up_if_array;
|
||||
|
||||
template<typename T>
|
||||
template<class T>
|
||||
struct up_if_array<T[]> {
|
||||
typedef std::unique_ptr<T[]> type;
|
||||
};
|
||||
|
@ -13,16 +13,16 @@
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
template<class T>
|
||||
struct up_if_not_array {
|
||||
typedef std::unique_ptr<T> type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template<class T>
|
||||
struct up_if_not_array<T[]> {
|
||||
};
|
||||
|
||||
template<typename T, std::size_t N>
|
||||
template<class T, std::size_t N>
|
||||
struct up_if_not_array<T[N]> {
|
||||
};
|
||||
}
|
||||
|
@ -9,151 +9,155 @@
|
||||
#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;
|
||||
T1* p1 = 0;
|
||||
T3* p2 = 0;
|
||||
typedef boost::detail::ms_init_tag R1;
|
||||
typedef boost::detail::ms_allocator<T, R1> A1;
|
||||
typedef boost::detail::ms_in_allocator_tag D1;
|
||||
std::size_t n1 = size * boost::detail::array_total<T1>::size;
|
||||
D1 d1(n1);
|
||||
A1 a1(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(size, &p2);
|
||||
shared_ptr<T> s1(p1, d1, a1);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
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);
|
||||
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_in_allocator_tag 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);
|
||||
p1 = reinterpret_cast<T1*>(p2);
|
||||
shared_ptr<T> s1(p1, d1, a1);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
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);
|
||||
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_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_in_allocator_tag 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);
|
||||
A1 a1(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(size, &p2);
|
||||
shared_ptr<T> s1(p1, d1, a1);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
boost::detail::ms_init<T2, M>(p2, n1, p3);
|
||||
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_in_allocator_tag 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);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
boost::detail::ms_init<T2, M>(p2, N, p3);
|
||||
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;
|
||||
T1* p1 = 0;
|
||||
T3* p2 = 0;
|
||||
typedef boost::detail::ms_noinit_tag R1;
|
||||
typedef boost::detail::ms_allocator<T, R1> A1;
|
||||
typedef boost::detail::ms_in_allocator_tag D1;
|
||||
std::size_t n1 = size * boost::detail::array_total<T1>::size;
|
||||
D1 d1(n1);
|
||||
A1 a1(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(size, &p2);
|
||||
shared_ptr<T> s1(p1, d1, a1);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
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);
|
||||
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_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_in_allocator_tag 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);
|
||||
p1 = reinterpret_cast<T1*>(p2);
|
||||
shared_ptr<T> s1(p1, d1, a1);
|
||||
A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
|
||||
a2->set(0);
|
||||
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);
|
||||
a2->set(p2);
|
||||
p1 = reinterpret_cast<T1*>(p2);
|
||||
return shared_ptr<T>(s1, p1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,14 +13,14 @@
|
||||
#include <boost/smart_ptr/detail/array_traits.hpp>
|
||||
|
||||
namespace boost {
|
||||
template<typename T>
|
||||
template<class T>
|
||||
inline typename boost::detail::up_if_array<T>::type
|
||||
make_unique(std::size_t size) {
|
||||
typedef typename boost::detail::array_inner<T>::type U;
|
||||
return std::unique_ptr<T>(new U[size]());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<class T>
|
||||
inline typename boost::detail::up_if_array<T>::type
|
||||
make_unique_noinit(std::size_t size) {
|
||||
typedef typename boost::detail::array_inner<T>::type U;
|
||||
|
@ -14,27 +14,27 @@
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
template<typename T>
|
||||
template<class T>
|
||||
inline typename boost::detail::up_if_not_array<T>::type
|
||||
make_unique() {
|
||||
return std::unique_ptr<T>(new T());
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<typename T, typename... Args>
|
||||
template<class T, class... Args>
|
||||
inline typename boost::detail::up_if_not_array<T>::type
|
||||
make_unique(Args&&... args) {
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
template<class T>
|
||||
inline typename boost::detail::up_if_not_array<T>::type
|
||||
make_unique(T&& value) {
|
||||
return std::unique_ptr<T>(new T(std::move(value)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<class T>
|
||||
inline typename boost::detail::up_if_not_array<T>::type
|
||||
make_unique_noinit() {
|
||||
return std::unique_ptr<T>(new T);
|
||||
|
@ -30,50 +30,50 @@
|
||||
user-supplied allocator, allowing finer control.</p>
|
||||
<h2><a name="synopsis">Synopsis</a></h2>
|
||||
<pre>namespace boost {
|
||||
template<typename U> // U is T[]
|
||||
template<class U> // U is T[]
|
||||
shared_ptr<U> <a href="#functions">make_shared</a>(size_t size);
|
||||
|
||||
template<typename U, typename A> // U is T[]
|
||||
template<class U, class A> // U is T[]
|
||||
shared_ptr<U> <a href="#functions">allocate_shared</a>(const A& allocator, size_t size);
|
||||
|
||||
template<typename U> // U is T[N]
|
||||
template<class U> // U is T[N]
|
||||
shared_ptr<U> <a href="#functions">make_shared</a>();
|
||||
|
||||
template<typename U, typename A> // U is T[N]
|
||||
template<class U, class A> // U is T[N]
|
||||
shared_ptr<U> <a href="#functions">allocate_shared</a>(const A& allocator);
|
||||
|
||||
template<typename U> // U is T[]
|
||||
template<class U> // U is T[]
|
||||
shared_ptr<U> <a href="#functions">make_shared</a>(size_t size, const T& value);
|
||||
|
||||
template<typename U, typename A> // U is T[]
|
||||
template<class U, class A> // U is T[]
|
||||
shared_ptr<U> <a href="#functions">allocate_shared</a>(const A& allocator, size_t size, const T& value);
|
||||
|
||||
template<typename U> // U is T[N]
|
||||
template<class U> // U is T[N]
|
||||
shared_ptr<U> <a href="#functions">make_shared</a>(const T& value);
|
||||
|
||||
template<typename U, typename A> // U is T[N]
|
||||
template<class U, class A> // U is T[N]
|
||||
shared_ptr<U> <a href="#functions">allocate_shared</a>(const A& allocator, const T& value);
|
||||
|
||||
template<typename U> // U is T[]
|
||||
template<class U> // U is T[]
|
||||
shared_ptr<U> <a href="#functions">make_shared_noinit</a>(size_t size);
|
||||
|
||||
template<typename U, typename A> // U is T[]
|
||||
template<class U, class A> // U is T[]
|
||||
shared_ptr<U> <a href="#functions">allocate_shared_noinit</a>(const A& allocator, size_t size);
|
||||
|
||||
template<typename U> // U is T[N]
|
||||
template<class U> // U is T[N]
|
||||
shared_ptr<U> <a href="#functions">make_shared_noinit</a>();
|
||||
|
||||
template<typename U, typename A> // U is T[N]
|
||||
template<class U, class A> // U is T[N]
|
||||
shared_ptr<U> <a href="#functions">allocate_shared_noinit</a>(const A& allocator);
|
||||
}</pre>
|
||||
<h2><a name="common">Common Requirements</a></h2>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
shared_ptr<U> make_shared(<em>args</em>);
|
||||
template<typename U, typename A>
|
||||
template<class U, class A>
|
||||
shared_ptr<U> allocate_shared(const A& allocator, <em>args</em>);
|
||||
template<typename U>
|
||||
template<class U>
|
||||
shared_ptr<U> make_shared_noinit(<em>args</em>);
|
||||
template<typename U, typename A>
|
||||
template<class U, class A>
|
||||
shared_ptr<U> allocate_shared_noinit(const A& allocator, <em>args</em>);</pre>
|
||||
<blockquote>
|
||||
<p><b>Requires:</b> <code>U</code> is of the form <code>T[]</code> or
|
||||
@ -157,9 +157,9 @@ template<typename U, typename A>
|
||||
structures such as the reference counts.</p>
|
||||
</blockquote>
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
shared_ptr<U> make_shared(size_t size);
|
||||
template<typename U, typename A>
|
||||
template<class U, class A>
|
||||
shared_ptr<U> allocate_shared(const A& allocator, size_t size);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> A <code>shared_ptr</code> to a value-initialized
|
||||
@ -172,9 +172,9 @@ template<typename U, typename A>
|
||||
boost::shared_ptr<int[][2]> a2 = boost::make_shared<int[][2]>(size);</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
shared_ptr<U> make_shared();
|
||||
template<typename U, typename A>
|
||||
template<class U, class A>
|
||||
shared_ptr<U> allocate_shared(const A& allocator);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> A <code>shared_ptr</code> to a value-initialized
|
||||
@ -187,9 +187,9 @@ template<typename U, typename A>
|
||||
boost::shared_ptr<int[4][2]> a2 = boost::make_shared<int[4][2]>();</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
shared_ptr<U> make_shared(size_t size, const T& value);
|
||||
template<typename U, typename A>
|
||||
template<class U, class A>
|
||||
shared_ptr<U> allocate_shared(const A& allocator, size_t size, const T& value);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> A <code>shared_ptr</code> to an object of type
|
||||
@ -203,9 +203,9 @@ template<typename U, typename A>
|
||||
boost::shared_ptr<int[][2]> a2 = boost::make_shared<int[][2]>(size, {1, 2});</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
shared_ptr<U> make_shared(const T& value);
|
||||
template<typename U, typename A>
|
||||
template<class U, class A>
|
||||
shared_ptr<U> allocate_shared(const A& allocator, const T& value);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> A <code>shared_ptr</code> to an object of type
|
||||
@ -219,9 +219,9 @@ template<typename U, typename A>
|
||||
boost::shared_ptr<int[4][2]> a2 = boost::make_shared<int[4][2]>({1, 2});</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
shared_ptr<U> make_shared_noinit(size_t size);
|
||||
template<typename U, typename A>
|
||||
template<class U, class A>
|
||||
shared_ptr<U> allocate_shared_noinit(const A& allocator, size_t size);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> A <code>shared_ptr</code> to a default-initialized
|
||||
@ -234,9 +234,9 @@ template<typename U, typename A>
|
||||
boost::shared_ptr<int[][2]> a2 = boost::make_shared_noinit<int[][2]>(size);</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
shared_ptr<U> make_shared_noinit();
|
||||
template<typename U, typename A>
|
||||
template<class U, class A>
|
||||
shared_ptr<U> allocate_shared_noinit(const A& allocator);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> A <code>shared_ptr</code> to a default-initialized
|
||||
@ -252,8 +252,9 @@ boost::shared_ptr<int[4][2]> a2 = boost::make_shared_noinit<int[4][2]&g
|
||||
<h2><a name="history">History</a></h2>
|
||||
<p>February 2014. Glen Fernandes updated overloads of make_shared and
|
||||
allocate_shared to conform to the specification in C++ standard paper
|
||||
<a href="#N3870">N3870</a> including resolving C++ standard library
|
||||
defect report 2070.</p>
|
||||
<a href="#N3870">N3870</a>, including resolving C++ standard library
|
||||
defect report 2070, and reduced the spatial overhead of the internal
|
||||
bookkeeping structures.</p>
|
||||
<p>November 2012. Glen Fernandes contributed implementations of
|
||||
make_shared and allocate_shared for arrays.</p>
|
||||
<h2><a name="references">References</a></h2>
|
||||
|
@ -18,30 +18,30 @@
|
||||
<code>unique_ptr</code> objects.</p>
|
||||
<h2><a name="synopsis">Synopsis</a></h2>
|
||||
<pre>namespace boost {
|
||||
template<typename U> // U is not array
|
||||
template<class U> // U is not array
|
||||
unique_ptr<U> <a href="#functions">make_unique</a>();
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
|
||||
template<typename U, typename... Args> // U is not array
|
||||
template<class U, class... Args> // U is not array
|
||||
unique_ptr<U> <a href="#functions">make_unique</a>(Args&&... args);
|
||||
#endif
|
||||
|
||||
template<typename U> // U is not array
|
||||
template<class U> // U is not array
|
||||
unique_ptr<U> <a href="#functions">make_unique</a>(U&& value);
|
||||
|
||||
template<typename U> // U is T[]
|
||||
template<class U> // U is T[]
|
||||
unique_ptr<U> <a href="#functions">make_unique</a>(size_t size);
|
||||
|
||||
template<typename U> // U is not array
|
||||
template<class U> // U is not array
|
||||
unique_ptr<U> <a href="#functions">make_unique_noinit</a>();
|
||||
|
||||
template<typename U> // U is T[]
|
||||
template<class U> // U is T[]
|
||||
unique_ptr<U> <a href="#functions">make_unique_noinit</a>(size_t size);
|
||||
}</pre>
|
||||
<h2><a name="common">Common Requirements</a></h2>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
unique_ptr<U> make_unique(<em>args</em>);
|
||||
template<typename U>
|
||||
template<class U>
|
||||
unique_ptr<U> make_unique_noinit(<em>args</em>);</pre>
|
||||
<blockquote>
|
||||
<p><b>Effects:</b> Allocates memory for an object of type <code>U</code>
|
||||
@ -73,7 +73,7 @@ template<typename U>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<h2><a name="functions">Free Functions</a></h2>
|
||||
<pre>template<typename U, typename... Args>
|
||||
<pre>template<class U, class... Args>
|
||||
unique_ptr<U> make_unique(Args&&... args);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> A unique_ptr to an object of type <code>U</code>,
|
||||
@ -86,7 +86,7 @@ unique_ptr<U> make_unique(Args&&... args);</pre>
|
||||
unique_ptr<point> p2 = boost::make_unique<point>(x, y);</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
unique_ptr<U> make_unique(U&& value);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> A unique_ptr to an object of type <code>U</code>,
|
||||
@ -99,7 +99,7 @@ unique_ptr<U> make_unique(U&& value);</pre>
|
||||
unique_ptr<point> p2 = boost::make_unique<point>({-10, 25});</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
unique_ptr<U> make_unique(size_t size);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> A unique_ptr to a value-initialized object of type
|
||||
@ -112,7 +112,7 @@ unique_ptr<U> make_unique(size_t size);</pre>
|
||||
unique_ptr<int[][2]> p2 = boost::make_unique<int[][2]>(2);</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
unique_ptr<U> make_unique_noinit();</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> A unique_ptr to a default-initialized object of
|
||||
@ -125,7 +125,7 @@ unique_ptr<U> make_unique_noinit();</pre>
|
||||
unique_ptr<point> p2 = boost::make_unique_noinit<point>();</pre>
|
||||
</blockquote>
|
||||
</blockquote>
|
||||
<pre>template<typename U>
|
||||
<pre>template<class U>
|
||||
unique_ptr<U> make_unique_noinit(size_t size);</pre>
|
||||
<blockquote>
|
||||
<p><b>Returns:</b> A unique_ptr to a default-initialized object of
|
||||
|
@ -83,6 +83,7 @@ import testing ;
|
||||
[ run shared_ptr_alloc11_test.cpp ]
|
||||
[ run allocate_shared_alloc11_test.cpp ]
|
||||
[ run allocate_shared_construct11_test.cpp ]
|
||||
[ run sp_interlocked_test.cpp ]
|
||||
|
||||
[ compile-fail array_fail_spa_sp_c.cpp ]
|
||||
[ compile-fail array_fail_sp_spa_c.cpp ]
|
||||
|
60
test/sp_interlocked_test.cpp
Normal file
60
test/sp_interlocked_test.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
//
|
||||
// sp_interlocked_test.cpp
|
||||
//
|
||||
// Copyright 2014 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#if defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
|
||||
|
||||
#include <boost/smart_ptr/detail/sp_interlocked.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
long x = 0, r;
|
||||
|
||||
r = BOOST_SP_INTERLOCKED_INCREMENT( &x );
|
||||
|
||||
BOOST_TEST( x == 1 );
|
||||
BOOST_TEST( r == 1 );
|
||||
|
||||
r = BOOST_SP_INTERLOCKED_DECREMENT( &x );
|
||||
|
||||
BOOST_TEST( x == 0 );
|
||||
BOOST_TEST( r == 0 );
|
||||
|
||||
r = BOOST_SP_INTERLOCKED_EXCHANGE( &x, 3 );
|
||||
|
||||
BOOST_TEST( x == 3 );
|
||||
BOOST_TEST( r == 0 );
|
||||
|
||||
r = BOOST_SP_INTERLOCKED_EXCHANGE_ADD( &x, 2 );
|
||||
|
||||
BOOST_TEST( x == 5 );
|
||||
BOOST_TEST( r == 3 );
|
||||
|
||||
r = BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE( &x, 0, 3 );
|
||||
|
||||
BOOST_TEST( x == 5 );
|
||||
BOOST_TEST( r == 5 );
|
||||
|
||||
r = BOOST_SP_INTERLOCKED_COMPARE_EXCHANGE( &x, 0, 5 );
|
||||
|
||||
BOOST_TEST( x == 0 );
|
||||
BOOST_TEST( r == 5 );
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user