Replace in_place_interface-based polymorphism with templated code

This commit is contained in:
Ion Gaztañaga
2024-09-13 12:06:48 +02:00
parent 615f64c9a0
commit 8a348c88ad
4 changed files with 202 additions and 281 deletions

View File

@@ -1,77 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2012. 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/interprocess for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
#define BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/interprocess/detail/config_begin.hpp>
#include <boost/interprocess/detail/workaround.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/container/detail/type_traits.hpp> //alignment_of, aligned_storage
#include <typeinfo> //typeid
//!\file
//!Describes an abstract interface for placement construction and destruction.
namespace boost {
namespace interprocess {
namespace ipcdetail {
struct in_place_interface
{
in_place_interface(std::size_t alignm, std::size_t sz, const char *tname)
: alignment(alignm), size(sz), type_name(tname)
{}
const std::size_t alignment;
const std::size_t size;
const char * const type_name;
virtual void construct_n(void *mem, std::size_t num) = 0;
virtual void destroy_n(void *mem, std::size_t num) = 0;
virtual ~in_place_interface(){}
};
template<class T>
struct placement_destroy : public in_place_interface
{
placement_destroy()
: in_place_interface(::boost::container::dtl::alignment_of<T>::value, sizeof(T), typeid(T).name())
{}
virtual void destroy_n(void *mem, std::size_t num) BOOST_OVERRIDE
{
T* memory = static_cast<T*>(mem);
for(std::size_t destroyed = 0; destroyed < num; ++destroyed)
(memory++)->~T();
}
virtual void construct_n(void *, std::size_t) BOOST_OVERRIDE {}
private:
void destroy(void *mem)
{ static_cast<T*>(mem)->~T(); }
};
}
}
} //namespace boost { namespace interprocess { namespace ipcdetail {
#include <boost/interprocess/detail/config_end.hpp>
#endif //#ifndef BOOST_INTERPROCESS_IN_PLACE_INTERFACE_HPP

View File

@@ -23,7 +23,6 @@
#include <boost/interprocess/detail/workaround.hpp>
// interprocess/detail
#include <boost/interprocess/detail/in_place_interface.hpp>
#include <boost/interprocess/detail/mpl.hpp>
#include <boost/move/utility_core.hpp>
#ifndef BOOST_INTERPROCESS_PERFECT_FORWARDING
@@ -43,11 +42,31 @@ namespace boost {
namespace interprocess {
namespace ipcdetail {
template<class T>
struct placement_destroy
{
placement_destroy()
{}
virtual void destroy_n(void *mem, std::size_t num)
{
T* memory = static_cast<T*>(mem);
for(std::size_t destroyed = 0; destroyed < num; ++destroyed)
(memory++)->~T();
}
private:
void destroy(void *mem)
{ static_cast<T*>(mem)->~T(); }
};
#ifdef BOOST_INTERPROCESS_PERFECT_FORWARDING
template<class T, bool is_iterator, class ...Args>
struct CtorArgN : public placement_destroy<T>
{
typedef T object_type;
typedef bool_<is_iterator> IsIterator;
typedef CtorArgN<T, is_iterator, Args...> self_t;
typedef typename build_number_seq<sizeof...(Args)>::type index_tuple_t;
@@ -64,7 +83,7 @@ struct CtorArgN : public placement_destroy<T>
: args_(args...)
{}
virtual void construct_n(void *mem, std::size_t num) BOOST_OVERRIDE
virtual void construct_n(void *mem, std::size_t num)
{
std::size_t constructed = 0;
BOOST_INTERPROCESS_TRY{
@@ -134,7 +153,7 @@ class named_proxy
CtorArgN<T, is_iterator, Args...> &&ctor_obj = CtorArgN<T, is_iterator, Args...>
(boost::forward<Args>(args)...);
return mp_mngr->template
generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);
generic_construct(ctor_obj, mp_name, m_num, m_find, m_dothrow);
}
//This operator allows --> named_new("Name")[3]; <-- syntax
@@ -154,7 +173,7 @@ struct CtorArg##N : placement_destroy<T>\
CtorArg##N ( BOOST_MOVE_UREF##N )\
BOOST_MOVE_COLON##N BOOST_MOVE_FWD_INIT##N{}\
\
virtual void construct_n(void *mem, std::size_t num) BOOST_OVERRIDE\
virtual void construct_n(void *mem, std::size_t num)\
{\
std::size_t constructed = 0;\
BOOST_INTERPROCESS_TRY{\
@@ -191,7 +210,7 @@ struct CtorIt##N : public placement_destroy<T>\
CtorIt##N ( BOOST_MOVE_VAL##N )\
BOOST_MOVE_COLON##N BOOST_MOVE_VAL_INIT##N{}\
\
virtual void construct_n(void *mem, std::size_t num) BOOST_OVERRIDE\
virtual void construct_n(void *mem, std::size_t num)\
{\
std::size_t constructed = 0;\
BOOST_INTERPROCESS_TRY{\
@@ -223,6 +242,7 @@ template
>
class named_proxy
{
typedef T object_type;
typedef typename SegmentManager::char_type char_type;
const char_type * mp_name;
SegmentManager * mp_mngr;
@@ -246,7 +266,7 @@ class named_proxy
, CtorArg##N<T BOOST_MOVE_I##N BOOST_MOVE_TARG##N> \
>::type ctor_obj_t;\
ctor_obj_t ctor_obj = ctor_obj_t( BOOST_MOVE_FWD##N );\
return mp_mngr->template generic_construct<T>(mp_name, m_num, m_find, m_dothrow, ctor_obj);\
return mp_mngr->template generic_construct(ctor_obj, mp_name, m_num, m_find, m_dothrow);\
}\
//
BOOST_MOVE_ITERATE_0TO9(BOOST_INTERPROCESS_NAMED_PROXY_CALL_OPERATOR)
@@ -264,7 +284,7 @@ class named_proxy
// ctor_obj_t;
// ctor_obj_t ctor_obj(p1, p2);
//
// return mp_mngr->template generic_construct<T>
// return mp_mngr->template generic_construct
// (mp_name, m_num, m_find, m_dothrow, ctor_obj);
// }
//

View File

@@ -27,7 +27,6 @@
// interprocess/detail
#include <boost/interprocess/detail/type_traits.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/in_place_interface.hpp>
// container/detail
#include <boost/container/detail/type_traits.hpp> //alignment_of
#include <boost/container/detail/minimal_char_traits_header.hpp>
@@ -41,9 +40,6 @@
// std
#include <cstddef> //std::size_t
//!\file
//!Describes the object placed in a memory segment that provides
//!named object allocation capabilities.
namespace boost{
namespace interprocess{
@@ -95,10 +91,6 @@ struct block_header
, m_alloc_type_sizeof_char( (unsigned char)((al_type << 5u) | ((unsigned char)szof_char & 0x1F)) )
{};
template<class T>
block_header &operator= (const T& )
{ return *this; }
size_type total_size() const
{
if(alloc_type() != anonymous_type){
@@ -169,18 +161,17 @@ struct block_header
template<class T>
static block_header *block_header_from_value(T *value)
{ return block_header_from_value(value, sizeof(T), ::boost::container::dtl::alignment_of<T>::value); }
static block_header *block_header_from_value(const void *value, std::size_t sz, std::size_t algn)
{
block_header * hdr =
// BOOST_ASSERT(is_ptr_aligned(value, algn));
const std::size_t algn = ::boost::container::dtl::alignment_of<T>::value;
block_header* hdr =
const_cast<block_header*>
(move_detail::force_ptr<const block_header*>(reinterpret_cast<const char*>(value) -
get_rounded_size(sizeof(block_header), algn)));
(void)sz;
(move_detail::force_ptr<const block_header*>(reinterpret_cast<const char*>(value) -
get_rounded_size(sizeof(block_header), algn)));
//Some sanity checks
BOOST_ASSERT(hdr->m_value_alignment == algn);
BOOST_ASSERT(hdr->m_value_bytes % sz == 0);
BOOST_ASSERT(hdr->m_value_bytes % sizeof(T) == 0);
return hdr;
}

View File

@@ -268,62 +268,6 @@ class segment_manager_base
//!Returns the size of the buffer previously allocated pointed by ptr
size_type size(const void *ptr) const
{ return MemoryAlgorithm::size(ptr); }
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
protected:
void * prot_anonymous_construct
(size_type num, bool dothrow, ipcdetail::in_place_interface &table)
{
typedef ipcdetail::block_header<size_type> block_header_t;
block_header_t block_info ( size_type(table.size*num)
, size_type(table.alignment)
, anonymous_type
, 1
, 0);
//Check if there is enough memory
void *ptr_struct = this->allocate_aligned(block_info.total_size(), table.alignment, nothrow<>::get());
if(!ptr_struct){
return ipcdetail::null_or_bad_alloc<void>(dothrow);
}
//Build scoped ptr to avoid leaks with constructor exception
ipcdetail::mem_algo_deallocator<MemoryAlgorithm> mem(ptr_struct, *this);
//Now construct the header
block_header_t * hdr = ::new(ptr_struct, boost_container_new_t()) block_header_t(block_info);
void *ptr = 0; //avoid gcc warning
ptr = hdr->value();
//Now call constructors
table.construct_n(ptr, num);
//All constructors successful, disable rollback
mem.release();
return ptr;
}
//!Calls the destructor and makes an anonymous deallocate
void prot_anonymous_destroy(const void *object, ipcdetail::in_place_interface &table)
{
//Get control data from associated with this object
typedef ipcdetail::block_header<size_type> block_header_t;
block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment);
//-------------------------------
//scoped_lock<rmutex> guard(m_header);
//-------------------------------
//This is not an anonymous object, the pointer is wrong!
BOOST_ASSERT(ctrl_data->alloc_type() == anonymous_type);
//Call destructors and free memory
//Build scoped ptr to avoid leaks with destructor exception
table.destroy_n(const_cast<void*>(object), ctrl_data->m_value_bytes/table.size);
this->deallocate(ctrl_data);
}
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
};
//!This object is placed in the beginning of memory segment and
@@ -533,15 +477,14 @@ class segment_manager
bool destroy(char_ptr_holder_t name)
{
BOOST_ASSERT(!name.is_anonymous());
ipcdetail::placement_destroy<T> dtor;
if(name.is_unique()){
return this->priv_generic_named_destroy<char>
( typeid(T).name(), m_header.m_unique_index , dtor, is_intrusive_t());
return this->priv_generic_named_destroy<T, char>
( typeid(T).name(), m_header.m_unique_index, is_intrusive_t());
}
else{
return this->priv_generic_named_destroy<CharType>
( name.get(), m_header.m_named_index, dtor, is_intrusive_t());
return this->priv_generic_named_destroy<T, CharType>
( name.get(), m_header.m_named_index, is_intrusive_t());
}
}
@@ -550,10 +493,7 @@ class segment_manager
template <class T>
void destroy_ptr(const T *p)
{
//If T is void transform it to char
typedef typename ipcdetail::char_if_void<T>::type data_t;
ipcdetail::placement_destroy<data_t> dtor;
priv_destroy_ptr(p, dtor);
priv_destroy_ptr(p);
}
//!Returns the name of an object created with construct/find_or_construct
@@ -699,15 +639,27 @@ class segment_manager
//!Generic named/anonymous new function. Offers all the possibilities,
//!such as throwing, search before creating, and the constructor is
//!encapsulated in an object function.
template<class T>
T *generic_construct(const CharType *name,
size_type num,
bool try2find,
bool dothrow,
ipcdetail::in_place_interface &table)
template<class Proxy>
typename Proxy::object_type * generic_construct
(Proxy& pr, const CharType *name, size_type num, bool try2find, bool dothrow)
{
return static_cast<T*>
(priv_generic_construct(name, num, try2find, dothrow, table));
typedef typename Proxy::object_type object_type;
//Security overflow check
if(num > ((size_type)-1)/sizeof(object_type)){
return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
}
if(name == 0){
return this->priv_anonymous_construct(pr, num, dothrow);
}
else if(name == reinterpret_cast<const CharType*>(-1)){
return this->priv_generic_named_construct
(pr, unique_type, typeid(object_type).name(), num, try2find, dothrow, m_header.m_unique_index, is_intrusive_t());
}
else{
return this->priv_generic_named_construct
(pr, named_type, name, num, try2find, dothrow, m_header.m_named_index, is_intrusive_t());
}
}
private:
@@ -719,15 +671,14 @@ class segment_manager
{
//The name can't be null, no anonymous object can be found by name
BOOST_ASSERT(name != 0);
ipcdetail::placement_destroy<T> table;
size_type sz;
void *ret;
if(name == reinterpret_cast<const CharType*>(-1)){
ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, sz, is_intrusive_t(), lock);
ret = priv_generic_find<T>(typeid(T).name(), m_header.m_unique_index, sz, is_intrusive_t(), lock);
}
else{
ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, sz, is_intrusive_t(), lock);
ret = priv_generic_find<T>(name, m_header.m_named_index, sz, is_intrusive_t(), lock);
}
return std::pair<T*, size_type>(static_cast<T*>(ret), sz);
}
@@ -736,52 +687,86 @@ class segment_manager
//!and the object count. On failure the first member of the
//!returned pair is 0.
template <class T>
std::pair<T*, size_type> priv_find_impl (const ipcdetail::unique_instance_t* name, bool lock)
std::pair<T*, size_type> priv_find_impl (const ipcdetail::unique_instance_t*, bool lock)
{
ipcdetail::placement_destroy<T> table;
size_type size;
void *ret = priv_generic_find<char>(name, m_header.m_unique_index, table, size, is_intrusive_t(), lock);
void *ret = priv_generic_find<T>(typeid(T).name(), m_header.m_unique_index, size, is_intrusive_t(), lock);
return std::pair<T*, size_type>(static_cast<T*>(ret), size);
}
void *priv_generic_construct
(const CharType *name, size_type num, bool try2find, bool dothrow, ipcdetail::in_place_interface &table)
template<class Proxy>
typename Proxy::object_type * priv_anonymous_construct(Proxy pr, size_type num, bool dothrow)
{
void *ret;
//Security overflow check
if(num > ((std::size_t)-1)/table.size){
return ipcdetail::null_or_bad_alloc<void>(dothrow);
typedef typename Proxy::object_type object_type;
BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment = boost::move_detail::alignment_of<object_type>::value;
block_header_t block_info ( size_type(sizeof(object_type)*num)
, size_type(t_alignment)
, anonymous_type
, 1
, 0);
//Check if there is enough memory
void *ptr_struct = this->allocate(block_info.total_size(), nothrow<>::get());
if(!ptr_struct){
return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
}
if(name == 0){
ret = this->prot_anonymous_construct(num, dothrow, table);
}
else if(name == reinterpret_cast<const CharType*>(-1)){
ret = this->priv_generic_named_construct<char>
(unique_type, table.type_name, num, try2find, dothrow, table, m_header.m_unique_index, is_intrusive_t());
}
else{
ret = this->priv_generic_named_construct<CharType>
(named_type, name, num, try2find, dothrow, table, m_header.m_named_index, is_intrusive_t());
}
return ret;
//Build scoped ptr to avoid leaks with constructor exception
ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
(ptr_struct, *static_cast<segment_manager_base_type*>(this));
//Now construct the header
block_header_t * hdr = ::new(ptr_struct, boost_container_new_t()) block_header_t(block_info);
void *ptr = 0; //avoid gcc warning
ptr = hdr->value();
//Now call constructors
pr.construct_n(ptr, num);
//All constructors successful, disable rollback
mem.release();
return static_cast<object_type*>(ptr);
}
void priv_destroy_ptr(const void *ptr, ipcdetail::in_place_interface &dtor)
//!Calls the destructor and makes an anonymous deallocate
template <class T>
void priv_anonymous_destroy(const T *object)
{
block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr, dtor.size, dtor.alignment);
//Get control data from associated with this object
block_header_t *ctrl_data = block_header_t::block_header_from_value(object);
//-------------------------------
//scoped_lock<rmutex> guard(m_header);
//-------------------------------
//This is not an anonymous object, the pointer is wrong!
BOOST_ASSERT(ctrl_data->alloc_type() == anonymous_type);
//Call destructors and free memory
//Build scoped ptr to avoid leaks with destructor exception
priv_destroy_n(object, ctrl_data->m_value_bytes/sizeof(T));
this->deallocate(ctrl_data);
}
template<class T>
void priv_destroy_ptr(const T *ptr)
{
block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr);
switch(ctrl_data->alloc_type()){
case anonymous_type:
this->prot_anonymous_destroy(ptr, dtor);
this->priv_anonymous_destroy(ptr);
break;
case named_type:
this->priv_generic_named_destroy<CharType>
(ctrl_data, m_header.m_named_index, dtor, is_node_index_t());
this->priv_generic_named_destroy<T, CharType>
(ctrl_data, m_header.m_named_index, is_node_index_t());
break;
case unique_type:
this->priv_generic_named_destroy<char>
(ctrl_data, m_header.m_unique_index, dtor, is_node_index_t());
this->priv_generic_named_destroy<T, char>
(ctrl_data, m_header.m_unique_index, is_node_index_t());
break;
default:
@@ -791,6 +776,13 @@ class segment_manager
}
}
template<class T>
static void priv_destroy_n(T* memory, std::size_t num)
{
for (std::size_t destroyed = 0; destroyed < num; ++destroyed)
(memory++)->~T();
}
//!Returns the name of an object created with construct/find_or_construct
//!functions. Does not throw
static const CharType *priv_get_instance_name(block_header_t *ctrl_data)
@@ -832,11 +824,10 @@ class segment_manager
return sizeof(segment_manager) - sizeof(segment_manager_base_t);
}
template <class CharT>
void *priv_generic_find
template <class T, class CharT>
T *priv_generic_find
(const CharT* name,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::in_place_interface &table,
size_type &length, ipcdetail::true_ is_intrusive, bool use_lock)
{
(void)is_intrusive;
@@ -861,19 +852,18 @@ class segment_manager
block_header_t *ctrl_data = it->get_block_header();
//Sanity check
BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
BOOST_ASSERT((ctrl_data->m_value_bytes % sizeof(T)) == 0);
BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT));
ret_ptr = ctrl_data->value();
length = ctrl_data->m_value_bytes/table.size;
length = ctrl_data->m_value_bytes/ sizeof(T);
}
return ret_ptr;
return static_cast<T*>(ret_ptr);
}
template <class CharT>
void *priv_generic_find
template <class T, class CharT>
T *priv_generic_find
(const CharT* name,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::in_place_interface &table,
size_type &length, ipcdetail::false_ is_intrusive, bool use_lock)
{
(void)is_intrusive;
@@ -898,43 +888,42 @@ class segment_manager
(ipcdetail::to_raw_pointer(it->second.m_ptr));
//Sanity check
BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
BOOST_ASSERT((ctrl_data->m_value_bytes % sizeof(T)) == 0);
BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT));
ret_ptr = ctrl_data->value();
length = ctrl_data->m_value_bytes/table.size;
length = ctrl_data->m_value_bytes/sizeof(T);
}
return ret_ptr;
return static_cast<T*>(ret_ptr);
}
template <class CharT>
template <class T, class CharT>
bool priv_generic_named_destroy
(block_header_t *block_header,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::in_place_interface &table, ipcdetail::true_ is_node_index)
(block_header_t *block_header
,IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index
,ipcdetail::true_ is_node_index)
{
(void)is_node_index;
typedef typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator index_it;
index_it *ihdr = block_header_t::template to_first_header<index_it>(block_header);
return this->priv_generic_named_destroy_impl<CharT>(*ihdr, index, table);
return this->priv_generic_named_destroy_impl<T, CharT>(*ihdr, index);
}
template <class CharT>
template <class T, class CharT>
bool priv_generic_named_destroy
(block_header_t *block_header,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::in_place_interface &table,
ipcdetail::false_ is_node_index)
(block_header_t *block_header
,IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index
,ipcdetail::false_ is_node_index)
{
(void)is_node_index;
CharT *name = static_cast<CharT*>(block_header->template name<CharT>());
return this->priv_generic_named_destroy<CharT>(name, index, table, is_intrusive_t());
return this->priv_generic_named_destroy<T, CharT>(name, index, is_intrusive_t());
}
template <class CharT>
template <class T, class CharT>
bool priv_generic_named_destroy(const CharT *name,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::in_place_interface &table, ipcdetail::true_ is_intrusive_index)
ipcdetail::true_ is_intrusive_index)
{
(void)is_intrusive_index;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
@@ -959,30 +948,28 @@ class segment_manager
block_header_t *ctrl_data = it->get_block_header();
intrusive_value_type *iv = intrusive_value_type::get_intrusive_value_type(ctrl_data);
void *memory = iv;
void *values = ctrl_data->value();
std::size_t num = ctrl_data->m_value_bytes/table.size;
//Sanity check
BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
BOOST_ASSERT((ctrl_data->m_value_bytes % sizeof(T)) == 0);
BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
//Erase node from index
index.erase(it);
//Call destructors and free memory
priv_destroy_n(static_cast<T*>(ctrl_data->value()), ctrl_data->m_value_bytes/sizeof(T));
//Destroy the headers
ctrl_data->~block_header_t();
iv->~intrusive_value_type();
//Call destructors and free memory
table.destroy_n(values, num);
this->deallocate(memory);
return true;
}
template <class CharT>
template <class T, class CharT>
bool priv_generic_named_destroy(const CharT *name,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::in_place_interface &table,
ipcdetail::false_ is_intrusive_index)
{
(void)is_intrusive_index;
@@ -1003,14 +990,13 @@ class segment_manager
//BOOST_ASSERT(0);
return false;
}
return this->priv_generic_named_destroy_impl<CharT>(it, index, table);
return this->priv_generic_named_destroy_impl<T, CharT>(it, index);
}
template <class CharT>
template <class T, class CharT>
bool priv_generic_named_destroy_impl
(const typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator &it,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::in_place_interface &table)
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
{
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > char_aware_index_type;
typedef typename char_aware_index_type::iterator index_it;
@@ -1021,22 +1007,16 @@ class segment_manager
char *stored_name = static_cast<char*>(static_cast<void*>(const_cast<CharT*>(it->first.name())));
(void)stored_name;
//Check if the distance between the name pointer and the memory pointer
//is correct (this can detect incorrect type in destruction)
std::size_t num = ctrl_data->m_value_bytes/table.size;
void *values = ctrl_data->value();
//Sanity check
BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
BOOST_ASSERT(static_cast<void*>(stored_name) == static_cast<void*>(ctrl_data->template name<CharT>()));
//Sanity checks
BOOST_ASSERT((ctrl_data->m_value_bytes % sizeof(T)) == 0);
BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
//Check if the distance between the name pointer and the memory pointer
BOOST_ASSERT(static_cast<void*>(stored_name) == static_cast<void*>(ctrl_data->template name<CharT>()));
//Erase node from index
index.erase(it);
//Destroy the header
ctrl_data->~block_header_t();
void *memory;
if(is_node_index_t::value){
index_it *ihdr = block_header_t::template
@@ -1049,25 +1029,31 @@ class segment_manager
}
//Call destructors and free memory
table.destroy_n(values, num);
priv_destroy_n(static_cast<T*>(ctrl_data->value()), ctrl_data->m_value_bytes/sizeof(T));
//Destroy the header
ctrl_data->~block_header_t();
this->deallocate(memory);
return true;
}
template<class CharT>
void * priv_generic_named_construct
(unsigned char type, const CharT *name, size_type num, bool try2find,
bool dothrow, ipcdetail::in_place_interface &table,
template<class Proxy, class CharT>
typename Proxy::object_type * priv_generic_named_construct
(Proxy pr, unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::true_ is_intrusive)
{
(void)is_intrusive;
std::size_t namelen = std::char_traits<CharT>::length(name);
block_header_t block_info ( size_type(table.size*num)
, size_type(table.alignment)
, type
, sizeof(CharT)
, namelen);
typedef typename Proxy::object_type object_type;
std::size_t namelen = std::char_traits<CharT>::length(name);
BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment = boost::move_detail::alignment_of<object_type>::value;
block_header_t block_info ( size_type(sizeof(object_type)*num)
, size_type(t_alignment)
, type
, sizeof(CharT)
, namelen);
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
typedef typename index_type_t::iterator index_it;
@@ -1110,9 +1096,9 @@ class segment_manager
//else return null
if(!insert_ret.second){
if(try2find){
return it->get_block_header()->value();
return static_cast<object_type*>(it->get_block_header()->value());
}
return ipcdetail::null_or_already_exists<void>(dothrow);
return ipcdetail::null_or_already_exists<object_type>(dothrow);
}
//Allocates buffer for name + data, this can throw (it hurts)
@@ -1121,7 +1107,7 @@ class segment_manager
//Check if there is enough memory
if (!buffer_ptr)
return ipcdetail::null_or_bad_alloc<void>(dothrow);
return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
//Now construct the intrusive hook plus the header
intrusive_value_type * intrusive_hdr = ::new(buffer_ptr, boost_container_new_t()) intrusive_value_type();
@@ -1156,30 +1142,31 @@ class segment_manager
value_eraser<index_type_t> v_eraser(index, it);
//Construct array, this can throw
table.construct_n(ptr, num);
pr.construct_n(ptr, num);
//Release rollbacks since construction was successful
v_eraser.release();
mem.release();
return ptr;
return static_cast<object_type*>(ptr);
}
//!Generic named new function for
//!named functions
template<class CharT>
void * priv_generic_named_construct
(unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow,
ipcdetail::in_place_interface &table,
template<class Proxy, class CharT>
typename Proxy::object_type * priv_generic_named_construct
(Proxy pr, unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::false_ is_intrusive)
{
(void)is_intrusive;
typedef typename Proxy::object_type object_type;
std::size_t namelen = std::char_traits<CharT>::length(name);
BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment = boost::move_detail::alignment_of<object_type>::value;
block_header_t block_info ( size_type(table.size*num)
, size_type(table.alignment)
, type
, sizeof(CharT)
, namelen);
block_header_t block_info ( size_type(sizeof(object_type)*num)
, size_type(t_alignment)
, type
, sizeof(CharT)
, namelen);
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
typedef typename index_type_t::key_type key_type;
@@ -1220,9 +1207,9 @@ class segment_manager
if(!insert_ret.second){
if(try2find){
block_header_t *hdr = static_cast<block_header_t*>(ipcdetail::to_raw_pointer(it->second.m_ptr));
return hdr->value();
return static_cast<object_type*>(hdr->value());
}
return ipcdetail::null_or_already_exists<void>(dothrow);
return ipcdetail::null_or_already_exists<object_type>(dothrow);
}
//Initialize the node value_eraser to erase inserted node
//if something goes wrong
@@ -1237,7 +1224,7 @@ class segment_manager
size_type total_size = block_info.template total_size_with_header<index_it>();
buffer_ptr = this->allocate(total_size, nothrow<>::get());
if(!buffer_ptr)
return ipcdetail::null_or_bad_alloc<void>(dothrow);
return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
index_it *idr = ::new(buffer_ptr, boost_container_new_t()) index_it(it);
hdr = block_header_t::template from_first_header<index_it>(idr);
}
@@ -1245,7 +1232,7 @@ class segment_manager
buffer_ptr = this->allocate(block_info.total_size(), nothrow<>::get());
//Check if there is enough memory
if (!buffer_ptr)
return ipcdetail::null_or_bad_alloc<void>(dothrow);
return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
hdr = static_cast<block_header_t*>(buffer_ptr);
}
@@ -1267,14 +1254,14 @@ class segment_manager
(buffer_ptr, *static_cast<segment_manager_base_type*>(this));
//Construct array, this can throw
table.construct_n(ptr, num);
pr.construct_n(ptr, num);
//All constructors successful, we don't want to release memory
mem.release();
//Release node v_eraser since construction was successful
v_eraser.release();
return ptr;
return static_cast<object_type*>(ptr);
}
private: