Bind allocator to element type, not scalar type

This commit is contained in:
Glen Fernandes
2019-05-15 01:24:53 -04:00
parent af92bd89ef
commit 3dffa64f58
4 changed files with 117 additions and 134 deletions

View File

@ -72,21 +72,19 @@ inline typename enable_if_<is_unbounded_array<T>::value,
local_shared_ptr<T> >::type local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator, std::size_t count) allocate_local_shared(const A& allocator, std::size_t count)
{ {
typedef typename remove_extent<T>::type type; typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::lsp_array_state<other> state; typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
std::size_t size = count * detail::sp_array_count<type, scalar>::value; detail::sp_array_result<other, base> result(allocator, count);
detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get(); base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, size, start); ::new(static_cast<void*>(node)) base(allocator, start, count);
detail::lsp_array_base& local = node->state().base(); detail::lsp_array_base& local = node->state().base();
local.set(node); local.set(node);
result.release(); result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
reinterpret_cast<type*>(start), &local); &local);
} }
template<class T, class A> template<class T, class A>
@ -94,23 +92,22 @@ inline typename enable_if_<is_bounded_array<T>::value,
local_shared_ptr<T> >::type local_shared_ptr<T> >::type
allocate_local_shared(const A& allocator) allocate_local_shared(const A& allocator)
{ {
typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum { enum {
size = detail::sp_array_count<T, scalar>::value count = extent<T>::value
}; };
typedef detail::lsp_size_array_state<other, size> state; typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::lsp_size_array_state<other, count> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get(); base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, size, start); ::new(static_cast<void*>(node)) base(allocator, start, count);
detail::lsp_array_base& local = node->state().base(); detail::lsp_array_base& local = node->state().base();
local.set(node); local.set(node);
result.release(); result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
reinterpret_cast<type*>(start), &local); &local);
} }
template<class T, class A> template<class T, class A>
@ -119,25 +116,19 @@ inline typename enable_if_<is_unbounded_array<T>::value,
allocate_local_shared(const A& allocator, std::size_t count, allocate_local_shared(const A& allocator, std::size_t count,
const typename remove_extent<T>::type& value) const typename remove_extent<T>::type& value)
{ {
typedef typename remove_extent<T>::type type; typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::lsp_array_state<other> state; typedef detail::lsp_array_state<other> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
enum { detail::sp_array_result<other, base> result(allocator, count);
total = detail::sp_array_count<type, scalar>::value
};
std::size_t size = count * total;
detail::sp_array_result<other, base> result(allocator, size);
base* node = result.get(); base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, size, ::new(static_cast<void*>(node)) base(allocator, start, count, value);
reinterpret_cast<const scalar*>(&value), total, start);
detail::lsp_array_base& local = node->state().base(); detail::lsp_array_base& local = node->state().base();
local.set(node); local.set(node);
result.release(); result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
reinterpret_cast<type*>(start), &local); &local);
} }
template<class T, class A> template<class T, class A>
@ -146,25 +137,22 @@ inline typename enable_if_<is_bounded_array<T>::value,
allocate_local_shared(const A& allocator, allocate_local_shared(const A& allocator,
const typename remove_extent<T>::type& value) const typename remove_extent<T>::type& value)
{ {
typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum { enum {
size = detail::sp_array_count<T, scalar>::value count = extent<T>::value
}; };
typedef detail::lsp_size_array_state<other, size> state; typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::lsp_size_array_state<other, count> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, count);
base* node = result.get(); base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, size, ::new(static_cast<void*>(node)) base(allocator, start, count, value);
reinterpret_cast<const scalar*>(&value),
detail::sp_array_count<type, scalar>::value, start);
detail::lsp_array_base& local = node->state().base(); detail::lsp_array_base& local = node->state().base();
local.set(node); local.set(node);
result.release(); result.release();
return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
reinterpret_cast<type*>(start), &local); &local);
} }
template<class T, class A> template<class T, class A>

View File

@ -9,12 +9,13 @@ Distributed under the Boost Software License, Version 1.0.
#define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
#include <boost/core/alloc_construct.hpp> #include <boost/core/alloc_construct.hpp>
#include <boost/core/first_scalar.hpp>
#include <boost/smart_ptr/shared_ptr.hpp> #include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/type_traits/alignment_of.hpp> #include <boost/type_traits/alignment_of.hpp>
#include <boost/type_traits/enable_if.hpp> #include <boost/type_traits/enable_if.hpp>
#include <boost/type_traits/extent.hpp>
#include <boost/type_traits/is_bounded_array.hpp> #include <boost/type_traits/is_bounded_array.hpp>
#include <boost/type_traits/is_unbounded_array.hpp> #include <boost/type_traits/is_unbounded_array.hpp>
#include <boost/type_traits/remove_all_extents.hpp>
#include <boost/type_traits/remove_cv.hpp> #include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_extent.hpp> #include <boost/type_traits/remove_extent.hpp>
#include <boost/type_traits/type_with_alignment.hpp> #include <boost/type_traits/type_with_alignment.hpp>
@ -23,15 +24,22 @@ namespace boost {
namespace detail { namespace detail {
template<class T> template<class T>
struct sp_array_scalar { struct sp_array_element {
typedef typename boost::remove_cv<typename typedef typename boost::remove_cv<typename
boost::remove_all_extents<T>::type>::type type; boost::remove_extent<T>::type>::type type;
}; };
template<class T, class U> template<class T>
struct sp_array_count { struct sp_array_count {
enum { enum {
value = sizeof(T) / sizeof(U) value = 1
};
};
template<class T, std::size_t N>
struct sp_array_count<T[N]> {
enum {
value = N * sp_array_count<T>::value
}; };
}; };
@ -127,39 +135,32 @@ struct sp_array_offset {
}; };
}; };
template<class T, class U> template<class U, class T>
struct sp_array_storage {
enum {
value = sp_array_alignment<T, U>::value
};
typedef typename boost::type_with_alignment<value>::type type;
};
template<class T, class U>
inline U* inline U*
sp_array_start(void* base) BOOST_SP_NOEXCEPT sp_array_start(T* base) BOOST_SP_NOEXCEPT
{ {
enum { enum {
size = sp_array_offset<T, U>::value size = sp_array_offset<T, U>::value
}; };
return reinterpret_cast<U*>(static_cast<char*>(base) + size); return reinterpret_cast<U*>(reinterpret_cast<char*>(base) + size);
} }
template<class A, class T> template<class A, class T>
class sp_array_creator { class sp_array_creator {
typedef typename A::value_type scalar; typedef typename A::value_type element;
enum { enum {
offset = sp_array_offset<T, scalar>::value offset = sp_array_offset<T, element>::value
}; };
typedef typename sp_array_storage<T, scalar>::type type; typedef typename boost::type_with_alignment<sp_array_alignment<T,
element>::value>::type type;
public: public:
template<class U> template<class U>
sp_array_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT sp_array_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
: other_(other), : other_(other),
size_(sp_objects<type>(offset + sizeof(scalar) * size)) { } size_(sp_objects<type>(offset + sizeof(element) * size)) { }
T* create() { T* create() {
return reinterpret_cast<T*>(other_.allocate(size_)); return reinterpret_cast<T*>(other_.allocate(size_));
@ -183,17 +184,22 @@ public:
typedef typename allocator::value_type type; typedef typename allocator::value_type type;
template<class A> template<class A>
sp_array_base(const A& other, std::size_t size, type* start) sp_array_base(const A& other, type* start, std::size_t size)
: state_(other, size) { : state_(other, size) {
boost::alloc_construct_n(state_.allocator(), start, state_.size()); boost::alloc_construct_n(state_.allocator(),
boost::first_scalar(start),
state_.size() * sp_array_count<type>::value);
} }
template<class A> template<class A, class U>
sp_array_base(const A& other, std::size_t size, const type* list, sp_array_base(const A& other, type* start, std::size_t size, const U& list)
std::size_t count, type* start)
: state_(other, size) { : state_(other, size) {
boost::alloc_construct_n(state_.allocator(), start, state_.size(), enum {
list, count); count = sp_array_count<type>::value
};
boost::alloc_construct_n(state_.allocator(),
boost::first_scalar(start), state_.size() * count,
boost::first_scalar(&list), count);
} }
T& state() BOOST_SP_NOEXCEPT { T& state() BOOST_SP_NOEXCEPT {
@ -202,7 +208,8 @@ public:
virtual void dispose() BOOST_SP_NOEXCEPT { virtual void dispose() BOOST_SP_NOEXCEPT {
boost::alloc_destroy_n(state_.allocator(), boost::alloc_destroy_n(state_.allocator(),
sp_array_start<sp_array_base, type>(this), state_.size()); boost::first_scalar(sp_array_start<type>(this)),
state_.size() * sp_array_count<type>::value);
} }
virtual void destroy() BOOST_SP_NOEXCEPT { virtual void destroy() BOOST_SP_NOEXCEPT {
@ -242,11 +249,11 @@ public:
} }
} }
T* get() const { T* get() const BOOST_SP_NOEXCEPT {
return result_; return result_;
} }
void release() { void release() BOOST_SP_NOEXCEPT {
result_ = 0; result_ = 0;
} }
@ -264,40 +271,37 @@ template<class T, class A>
inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, std::size_t count) allocate_shared(const A& allocator, std::size_t count)
{ {
typedef typename remove_extent<T>::type type; typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::sp_array_state<other> state; typedef detail::sp_array_state<other> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
std::size_t size = count * detail::sp_array_count<type, scalar>::value; detail::sp_array_result<other, base> result(allocator, count);
detail::sp_array_result<other, base> result(allocator, size); base* node = result.get();
detail::sp_counted_base* node = result.get(); element* start = detail::sp_array_start<element>(node);
scalar* start = detail::sp_array_start<base, scalar>(node); ::new(static_cast<void*>(node)) base(allocator, start, count);
::new(static_cast<void*>(node)) base(allocator, size, start);
result.release(); result.release();
return shared_ptr<T>(detail::sp_internal_constructor_tag(), return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
reinterpret_cast<type*>(start), detail::shared_count(node)); detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
} }
template<class T, class A> template<class T, class A>
inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator) allocate_shared(const A& allocator)
{ {
typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum { enum {
size = detail::sp_array_count<T, scalar>::value count = extent<T>::value
}; };
typedef detail::sp_size_array_state<other, size> state; typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::sp_size_array_state<other, extent<T>::value> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, count);
detail::sp_counted_base* node = result.get(); base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, size, start); ::new(static_cast<void*>(node)) base(allocator, start, count);
result.release(); result.release();
return shared_ptr<T>(detail::sp_internal_constructor_tag(), return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
reinterpret_cast<type*>(start), detail::shared_count(node)); detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
} }
template<class T, class A> template<class T, class A>
@ -305,23 +309,17 @@ inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, std::size_t count, allocate_shared(const A& allocator, std::size_t count,
const typename remove_extent<T>::type& value) const typename remove_extent<T>::type& value)
{ {
typedef typename remove_extent<T>::type type; typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_array_scalar<T>::type scalar; typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
typedef detail::sp_array_state<other> state; typedef detail::sp_array_state<other> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
enum { detail::sp_array_result<other, base> result(allocator, count);
total = detail::sp_array_count<type, scalar>::value base* node = result.get();
}; element* start = detail::sp_array_start<element>(node);
std::size_t size = count * total; ::new(static_cast<void*>(node)) base(allocator, start, count, value);
detail::sp_array_result<other, base> result(allocator, size);
detail::sp_counted_base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node);
::new(static_cast<void*>(node)) base(allocator, size,
reinterpret_cast<const scalar*>(&value), total, start);
result.release(); result.release();
return shared_ptr<T>(detail::sp_internal_constructor_tag(), return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
reinterpret_cast<type*>(start), detail::shared_count(node)); detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
} }
template<class T, class A> template<class T, class A>
@ -329,23 +327,20 @@ inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
allocate_shared(const A& allocator, allocate_shared(const A& allocator,
const typename remove_extent<T>::type& value) const typename remove_extent<T>::type& value)
{ {
typedef typename remove_extent<T>::type type;
typedef typename detail::sp_array_scalar<T>::type scalar;
typedef typename detail::sp_bind_allocator<A, scalar>::type other;
enum { enum {
size = detail::sp_array_count<T, scalar>::value count = extent<T>::value
}; };
typedef detail::sp_size_array_state<other, size> state; typedef typename detail::sp_array_element<T>::type element;
typedef typename detail::sp_bind_allocator<A, element>::type other;
typedef detail::sp_size_array_state<other, extent<T>::value> state;
typedef detail::sp_array_base<state> base; typedef detail::sp_array_base<state> base;
detail::sp_array_result<other, base> result(allocator, size); detail::sp_array_result<other, base> result(allocator, count);
detail::sp_counted_base* node = result.get(); base* node = result.get();
scalar* start = detail::sp_array_start<base, scalar>(node); element* start = detail::sp_array_start<element>(node);
::new(static_cast<void*>(node)) base(allocator, size, ::new(static_cast<void*>(node)) base(allocator, start, count, value);
reinterpret_cast<const scalar*>(&value),
detail::sp_array_count<type, scalar>::value, start);
result.release(); result.release();
return shared_ptr<T>(detail::sp_internal_constructor_tag(), return shared_ptr<T>(detail::sp_internal_constructor_tag(), start,
reinterpret_cast<type*>(start), detail::shared_count(node)); detail::shared_count(static_cast<detail::sp_counted_base*>(node)));
} }
template<class T, class A> template<class T, class A>

View File

@ -20,7 +20,7 @@ inline typename enable_if_<is_bounded_array<T>::value,
make_local_shared() make_local_shared()
{ {
return boost::allocate_local_shared<T>(boost::default_allocator<typename return boost::allocate_local_shared<T>(boost::default_allocator<typename
detail::sp_array_scalar<T>::type>()); detail::sp_array_element<T>::type>());
} }
template<class T> template<class T>
@ -29,7 +29,7 @@ inline typename enable_if_<is_bounded_array<T>::value,
make_local_shared(const typename remove_extent<T>::type& value) make_local_shared(const typename remove_extent<T>::type& value)
{ {
return boost::allocate_local_shared<T>(boost::default_allocator<typename return boost::allocate_local_shared<T>(boost::default_allocator<typename
detail::sp_array_scalar<T>::type>(), value); detail::sp_array_element<T>::type>(), value);
} }
template<class T> template<class T>
@ -38,7 +38,7 @@ inline typename enable_if_<is_unbounded_array<T>::value,
make_local_shared(std::size_t size) make_local_shared(std::size_t size)
{ {
return boost::allocate_local_shared<T>(boost::default_allocator<typename return boost::allocate_local_shared<T>(boost::default_allocator<typename
detail::sp_array_scalar<T>::type>(), size); detail::sp_array_element<T>::type>(), size);
} }
template<class T> template<class T>
@ -48,7 +48,7 @@ make_local_shared(std::size_t size,
const typename remove_extent<T>::type& value) const typename remove_extent<T>::type& value)
{ {
return boost::allocate_local_shared<T>(boost::default_allocator<typename return boost::allocate_local_shared<T>(boost::default_allocator<typename
detail::sp_array_scalar<T>::type>(), size, value); detail::sp_array_element<T>::type>(), size, value);
} }
template<class T> template<class T>
@ -57,7 +57,7 @@ inline typename enable_if_<is_bounded_array<T>::value,
make_local_shared_noinit() make_local_shared_noinit()
{ {
return boost::allocate_local_shared_noinit<T>(boost:: return boost::allocate_local_shared_noinit<T>(boost::
default_allocator<typename detail::sp_array_scalar<T>::type>()); default_allocator<typename detail::sp_array_element<T>::type>());
} }
template<class T> template<class T>
@ -66,7 +66,7 @@ inline typename enable_if_<is_unbounded_array<T>::value,
make_local_shared_noinit(std::size_t size) make_local_shared_noinit(std::size_t size)
{ {
return boost::allocate_local_shared_noinit<T>(boost:: return boost::allocate_local_shared_noinit<T>(boost::
default_allocator<typename detail::sp_array_scalar<T>::type>(), size); default_allocator<typename detail::sp_array_element<T>::type>(), size);
} }
} /* boost */ } /* boost */

View File

@ -18,7 +18,7 @@ inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared() make_shared()
{ {
return boost::allocate_shared<T>(boost::default_allocator<typename return boost::allocate_shared<T>(boost::default_allocator<typename
detail::sp_array_scalar<T>::type>()); detail::sp_array_element<T>::type>());
} }
template<class T> template<class T>
@ -26,7 +26,7 @@ inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared(const typename remove_extent<T>::type& value) make_shared(const typename remove_extent<T>::type& value)
{ {
return boost::allocate_shared<T>(boost::default_allocator<typename return boost::allocate_shared<T>(boost::default_allocator<typename
detail::sp_array_scalar<T>::type>(), value); detail::sp_array_element<T>::type>(), value);
} }
template<class T> template<class T>
@ -34,7 +34,7 @@ inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared(std::size_t size) make_shared(std::size_t size)
{ {
return boost::allocate_shared<T>(boost::default_allocator<typename return boost::allocate_shared<T>(boost::default_allocator<typename
detail::sp_array_scalar<T>::type>(), size); detail::sp_array_element<T>::type>(), size);
} }
template<class T> template<class T>
@ -42,7 +42,7 @@ inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared(std::size_t size, const typename remove_extent<T>::type& value) make_shared(std::size_t size, const typename remove_extent<T>::type& value)
{ {
return boost::allocate_shared<T>(boost::default_allocator<typename return boost::allocate_shared<T>(boost::default_allocator<typename
detail::sp_array_scalar<T>::type>(), size, value); detail::sp_array_element<T>::type>(), size, value);
} }
template<class T> template<class T>
@ -50,7 +50,7 @@ inline typename enable_if_<is_bounded_array<T>::value, shared_ptr<T> >::type
make_shared_noinit() make_shared_noinit()
{ {
return boost::allocate_shared_noinit<T>(boost::default_allocator<typename return boost::allocate_shared_noinit<T>(boost::default_allocator<typename
detail::sp_array_scalar<T>::type>()); detail::sp_array_element<T>::type>());
} }
template<class T> template<class T>
@ -58,7 +58,7 @@ inline typename enable_if_<is_unbounded_array<T>::value, shared_ptr<T> >::type
make_shared_noinit(std::size_t size) make_shared_noinit(std::size_t size)
{ {
return boost::allocate_shared_noinit<T>(boost::default_allocator<typename return boost::allocate_shared_noinit<T>(boost::default_allocator<typename
detail::sp_array_scalar<T>::type>(), size); detail::sp_array_element<T>::type>(), size);
} }
} /* boost */ } /* boost */