Implement allocate_local_shared for arrays

Also fix the local_shared_ptr constructor to use element_type
This commit is contained in:
Glen Fernandes
2017-06-29 12:46:39 -04:00
parent 48294c483f
commit be736e5088
18 changed files with 2047 additions and 48 deletions

View File

@@ -0,0 +1,240 @@
/*
Copyright 2017 Glen Joseph Fernandes
(glenjofe@gmail.com)
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
#include <boost/smart_ptr/allocate_shared_array.hpp>
#include <boost/smart_ptr/local_shared_ptr.hpp>
namespace boost {
namespace detail {
template<class>
struct lsp_if_array { };
template<class T>
struct lsp_if_array<T[]> {
typedef boost::local_shared_ptr<T[]> type;
};
template<class>
struct lsp_if_size_array { };
template<class T, std::size_t N>
struct lsp_if_size_array<T[N]> {
typedef boost::local_shared_ptr<T[N]> type;
};
class lsp_array_base
: public local_counted_base {
public:
void set(sp_counted_base* base) BOOST_SP_NOEXCEPT {
shared_count(base).swap(count_);
}
virtual void local_cb_destroy() BOOST_SP_NOEXCEPT {
shared_count().swap(count_);
}
virtual shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT {
return count_;
}
private:
shared_count count_;
};
template<class A>
class lsp_array_state
: public lsp_array_base {
public:
typedef A type;
lsp_array_state(const A& allocator, std::size_t size) BOOST_SP_NOEXCEPT
: allocator_(allocator),
size_(size) { }
A& allocator() BOOST_SP_NOEXCEPT {
return allocator_;
}
std::size_t size() const BOOST_SP_NOEXCEPT {
return size_;
}
private:
A allocator_;
std::size_t size_;
};
template<class A, std::size_t N>
class lsp_size_array_state
: public lsp_array_base {
public:
typedef A type;
lsp_size_array_state(const A& allocator, std::size_t) BOOST_SP_NOEXCEPT
: allocator_(allocator) { }
A& allocator() BOOST_SP_NOEXCEPT {
return allocator_;
}
BOOST_CONSTEXPR std::size_t size() const BOOST_SP_NOEXCEPT {
return N;
}
private:
A allocator_;
};
} /* detail */
template<class T, class A>
inline typename detail::lsp_if_array<T>::type
allocate_local_shared(const A& allocator, std::size_t count)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state> base;
std::size_t size = count * detail::sp_array_count<type>::value;
detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get();
::new(static_cast<void*>(node)) base(allocator, size);
detail::lsp_array_base& local = node->state();
local.set(node);
void* start = detail::sp_array_start<scalar>(node);
result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
static_cast<type*>(start), &local);
}
template<class T, class A>
inline typename detail::lsp_if_size_array<T>::type
allocate_local_shared(const A& allocator)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T>::value
};
typedef detail::lsp_size_array_state<other, size> state;
typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get();
::new(static_cast<void*>(node)) base(allocator, size);
detail::lsp_array_base& local = node->state();
local.set(node);
void* start = detail::sp_array_start<scalar>(node);
result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
static_cast<type*>(start), &local);
}
template<class T, class A>
inline typename detail::lsp_if_array<T>::type
allocate_local_shared(const A& allocator, std::size_t count,
const typename detail::sp_array_element<T>::type& value)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state> base;
std::size_t size = count * detail::sp_array_count<type>::value;
detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get();
::new(static_cast<void*>(node)) base(allocator, size,
reinterpret_cast<const scalar*>(&value),
detail::sp_array_count<type>::value);
detail::lsp_array_base& local = node->state();
local.set(node);
void* start = detail::sp_array_start<scalar>(node);
result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
static_cast<type*>(start), &local);
}
template<class T, class A>
inline typename detail::lsp_if_size_array<T>::type
allocate_local_shared(const A& allocator,
const typename detail::sp_array_element<T>::type& value)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T>::value
};
typedef detail::lsp_size_array_state<other, size> state;
typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get();
::new(static_cast<void*>(node)) base(allocator, size,
reinterpret_cast<const scalar*>(&value),
detail::sp_array_count<type>::value);
detail::lsp_array_base& local = node->state();
local.set(node);
void* start = detail::sp_array_start<scalar>(node);
result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
static_cast<type*>(start), &local);
}
template<class T, class A>
inline typename detail::lsp_if_array<T>::type
allocate_local_shared_noinit(const A& allocator, std::size_t count)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state, false> base;
std::size_t size = count * detail::sp_array_count<type>::value;
detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get();
::new(static_cast<void*>(node)) base(detail::sp_default(),
allocator, size);
detail::lsp_array_base& local = node->state();
local.set(node);
void* start = detail::sp_array_start<scalar>(node);
result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
static_cast<type*>(start), &local);
}
template<class T, class A>
inline typename detail::lsp_if_size_array<T>::type
allocate_local_shared_noinit(const A& allocator)
{
typedef typename detail::sp_array_element<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum {
size = detail::sp_array_count<T>::value
};
typedef detail::lsp_size_array_state<other, size> state;
typedef detail::sp_array_base<state, false> base;
detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get();
::new(static_cast<void*>(node)) base(detail::sp_default(),
allocator, size);
detail::lsp_array_base& local = node->state();
local.set(node);
void* start = detail::sp_array_start<scalar>(node);
result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
static_cast<type*>(start), &local);
}
} /* boost */
#endif

View File

@@ -502,6 +502,10 @@ public:
state_.size());
}
T& state() BOOST_SP_NOEXCEPT {
return state_;
}
virtual void dispose() {
sp_array_destroy<E>(state_.allocator(), sp_array_start<type>(this),
state_.size());

View File

@@ -149,7 +149,7 @@ public:
#endif
// internal constructor, used by make_shared
BOOST_CONSTEXPR local_shared_ptr( boost::detail::lsp_internal_constructor_tag, T * px_, boost::detail::local_counted_base * pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ )
BOOST_CONSTEXPR local_shared_ptr( boost::detail::lsp_internal_constructor_tag, element_type * px_, boost::detail::local_counted_base * pn_ ) BOOST_SP_NOEXCEPT : px( px_ ), pn( pn_ )
{
}

View File

@@ -1,63 +1,67 @@
#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP_INCLUDED
#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP_INCLUDED
/*
Copyright 2017 Peter Dimov
Copyright 2017 Glen Joseph Fernandes
(glenjofe@gmail.com)
// make_local_shared_array.hpp
//
// Copyright 2017 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
//
// See http://www.boost.org/libs/smart_ptr/ for documentation.
Distributed under the Boost Software License, Version 1.0.
(http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP
#define BOOST_SMART_PTR_MAKE_LOCAL_SHARED_ARRAY_HPP
#include <boost/config.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <utility>
#include <cstddef>
#include <boost/smart_ptr/allocate_local_shared_array.hpp>
namespace boost
namespace boost {
template<class T>
inline typename detail::lsp_if_size_array<T>::type
make_local_shared()
{
namespace detail
{
template<class T> struct lsp_if_array
{
};
template<class T> struct lsp_if_array<T[]>
{
typedef boost::local_shared_ptr<T[]> type;
};
template<class T, std::size_t N> struct lsp_if_array<T[N]>
{
typedef boost::local_shared_ptr<T[N]> type;
};
} // namespace detail
template<class T, class... Args> typename boost::detail::lsp_if_array<T>::type make_local_shared( Args&&... args )
{
return boost::make_shared<T>( std::forward<Args>(args)... );
return boost::allocate_local_shared<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>());
}
template<class T, class... Args> typename boost::detail::lsp_if_array<T>::type make_local_shared_noinit( Args&&... args )
template<class T>
inline typename detail::lsp_if_size_array<T>::type
make_local_shared(const typename detail::sp_array_element<T>::type& value)
{
return boost::make_shared_noinit<T>( std::forward<Args>(args)... );
return boost::allocate_local_shared<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), value);
}
template<class T, class A, class... Args> typename boost::detail::lsp_if_array<T>::type allocate_local_shared( A const & a, Args&&... args )
template<class T>
inline typename detail::lsp_if_array<T>::type
make_local_shared(std::size_t size)
{
return boost::allocate_shared<T>( a, std::forward<Args>(args)... );
return boost::allocate_local_shared<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), size);
}
template<class T, class A, class... Args> typename boost::detail::lsp_if_array<T>::type allocate_local_shared_noinit( A const & a, Args&&... args )
template<class T>
inline typename detail::lsp_if_array<T>::type
make_local_shared(std::size_t size,
const typename detail::sp_array_element<T>::type& value)
{
return boost::allocate_shared_noinit<T>( a, std::forward<Args>(args)... );
return boost::allocate_local_shared<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), size, value);
}
} // namespace boost
template<class T>
inline typename detail::lsp_if_size_array<T>::type
make_local_shared_noinit()
{
return allocate_local_shared_noinit<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>());
}
#endif // #ifndef BOOST_SMART_PTR_MAKE_SHARED_OBJECT_HPP_INCLUDED
template<class T>
inline typename detail::lsp_if_array<T>::type
make_local_shared_noinit(std::size_t size)
{
return allocate_local_shared_noinit<T>(std::allocator<typename
detail::sp_array_scalar<T>::type>(), size);
}
} /* boost */
#endif