Refactor quasi-duplicated priv_generic_named_destroy and priv_generic_named_construct implementations.

This commit is contained in:
Ion Gaztañaga
2024-09-17 22:06:22 +02:00
parent b53ffe5925
commit 0665fd3f1a
6 changed files with 212 additions and 302 deletions

View File

@@ -144,21 +144,6 @@ struct block_header
return get_rounded_size(size_type(sizeof(block_header)), size_type(m_value_alignment));
}
template<class CharType>
bool less_comp(const block_header &b) const
{
return m_num_char < b.m_num_char ||
(m_num_char < b.m_num_char &&
std::char_traits<CharType>::compare(name<CharType>(), b.name<CharType>(), m_num_char) < 0);
}
template<class CharType>
bool equal_comp(const block_header &b) const
{
return m_num_char == b.m_num_char &&
std::char_traits<CharType>::compare(name<CharType>(), b.name<CharType>(), m_num_char) == 0;
}
template<class T>
static block_header *block_header_from_value(T *value)
{
@@ -186,6 +171,10 @@ struct block_header
return hdr;
}
template<class Header>
static const block_header *from_first_header(const Header *header)
{ return from_first_header(const_cast<Header*>(header)); }
template<class Header>
static Header *to_first_header(block_header *bheader)
{
@@ -207,28 +196,16 @@ struct intrusive_compare_key
: mp_str(str), m_len(len)
{}
const CharT *str() const
{ return mp_str; }
std::size_t len() const
{ return m_len; }
const CharT * mp_str;
std::size_t m_len;
};
template<class IndexType, bool IsIntrusive>
struct compare_key_impl
{
typedef typename IndexType::compare_key_type type;
};
template<class IndexType>
struct compare_key_impl<IndexType, false>
{
typedef typename IndexType::key_type type;
};
template<class IndexType>
struct compare_key
: compare_key_impl<IndexType, is_intrusive_index<IndexType>::value>
{};
//!This struct indicates an anonymous object creation
//!allocation
@@ -270,26 +247,14 @@ struct intrusive_value_type_impl
intrusive_value_type_impl(){}
enum { BlockHdrAlignment = ::boost::container::dtl::alignment_of<block_header_t>::value };
block_header_t *get_block_header()
{ return block_header_t::from_first_header(this); }
block_header_t *get_block_header() const
{
return const_cast<block_header_t*>
(move_detail::force_ptr<const block_header_t *>(reinterpret_cast<const char*>(this) +
get_rounded_size(size_type(sizeof(*this)), size_type(BlockHdrAlignment))));
}
bool operator <(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
{ return (this->get_block_header())->template less_comp<CharType>(*other.get_block_header()); }
bool operator ==(const intrusive_value_type_impl<Hook, CharType, SizeType> & other) const
{ return (this->get_block_header())->template equal_comp<CharType>(*other.get_block_header()); }
const block_header_t *get_block_header() const
{ return block_header_t::from_first_header(this); }
static intrusive_value_type_impl *get_intrusive_value_type(block_header_t *hdr)
{
return move_detail::force_ptr<intrusive_value_type_impl*>(reinterpret_cast<char*>(hdr) -
get_rounded_size(size_type(sizeof(intrusive_value_type_impl)), size_type(BlockHdrAlignment)));
}
{ return block_header_t::template to_first_header<intrusive_value_type_impl>(hdr); }
CharType *name() const
{ return get_block_header()->template name<CharType>(); }

View File

@@ -61,29 +61,55 @@ struct flat_map_index_aux
template <class MapConfig>
class flat_map_index
//Derive class from flat_map specialization
: public flat_map_index_aux<MapConfig>::index_t
: private flat_map_index_aux<MapConfig>::index_t
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef flat_map_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t base_type;
typedef typename index_aux::
segment_manager_base segment_manager_base;
typedef typename base_type::key_type key_type;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
using base_type::begin;
using base_type::end;
using base_type::size;
using base_type::erase;
using base_type::shrink_to_fit;
using base_type::reserve;
typedef typename base_type::iterator iterator;
typedef typename base_type::const_iterator const_iterator;
typedef typename base_type::value_type value_type;
typedef typename MapConfig::compare_key_type compare_key_type;
typedef iterator insert_commit_data;
typedef iterator index_data_t;
//!Constructor. Takes a pointer to the segment manager. Can throw
flat_map_index(segment_manager_base *segment_mngr)
: base_type(typename index_aux::key_less(),
typename index_aux::allocator_type(segment_mngr))
{}
//!This reserves memory to optimize the insertion of n elements in the index
void reserve(typename segment_manager_base::size_type n)
{ base_type::reserve(n); }
std::pair<iterator, bool> insert_check
(const compare_key_type& key, insert_commit_data&)
{
std::pair<iterator, bool> r;
r.first = this->base_type::find(key_type(key.str(), key.len()));
r.second = r.first == this->base_type::end();
return r;
}
//!This frees all unnecessary memory
void shrink_to_fit()
{ base_type::shrink_to_fit(); }
iterator insert_commit
(const compare_key_type &k, void *context, index_data_t&, insert_commit_data& )
{
//Now commit the insertion using previous context data
typedef typename base_type::mapped_type mapped_type;
return this->base_type::insert(value_type(key_type(k.str(), k.len()), mapped_type(context))).first;
}
iterator find(const compare_key_type& k)
{ return this->base_type::find(key_type(k.str(), k.len())); }
};
}} //namespace boost { namespace interprocess

View File

@@ -51,42 +51,13 @@ struct iset_index_aux
< bi::void_pointer<void_pointer>
, bi::optimize_size<true>
>::type derivation_hook;
typedef typename MapConfig::char_type char_type;
typedef typename MapConfig::template
intrusive_value_type<derivation_hook>::type value_type;
typedef std::less<value_type> value_compare;
typedef typename bi::make_set
< value_type
, bi::base_hook<derivation_hook>
>::type index_t;
};
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Index type based in boost::intrusive::set.
//!Just derives from boost::intrusive::set
//!and defines the interface needed by managed memory segments*/
template <class MapConfig>
class iset_index
//Derive class from map specialization
: public iset_index_aux<MapConfig>::index_t
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef iset_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t index_type;
typedef typename MapConfig::char_type char_type;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
typedef typename MapConfig::compare_key_type compare_key_type;
public:
typedef typename index_type::iterator iterator;
typedef typename index_type::const_iterator const_iterator;
typedef typename index_type::insert_commit_data insert_commit_data;
typedef typename index_type::value_type value_type;
typedef typename MapConfig::compare_key_type compare_key_type;
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
struct intrusive_key_value_less
struct less_function
{
bool operator()(const compare_key_type&i, const value_type &b) const
{
@@ -105,11 +76,56 @@ class iset_index
std::char_traits<char_type>::compare
(b.name(), i.mp_str, i.m_len) < 0);
}
bool operator()(const value_type& a, const value_type& b) const
{
std::size_t alen = a.name_length();
std::size_t blen = b.name_length();
return (alen < blen) ||
(alen == blen &&
std::char_traits<char_type>::compare
(a.name(), b.name(), alen) < 0);
}
};
typedef std::less<value_type> value_compare;
typedef typename bi::make_set
< value_type
, bi::base_hook<derivation_hook>
, bi::compare<less_function>
>::type index_t;
};
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
//!Index type based in boost::intrusive::set.
//!Just derives from boost::intrusive::set
//!and defines the interface needed by managed memory segments*/
template <class MapConfig>
class iset_index
//Derive class from map specialization
: private iset_index_aux<MapConfig>::index_t
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef iset_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t index_type;
typedef typename MapConfig::char_type char_type;
typedef typename index_aux::less_function less_function;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
typedef typename index_type::iterator iterator;
typedef typename index_type::const_iterator const_iterator;
typedef typename index_type::insert_commit_data insert_commit_data;
typedef typename index_type::value_type value_type;
typedef typename MapConfig::compare_key_type compare_key_type;
typedef value_type index_data_t;
public:
using index_type::begin;
using index_type::end;
using index_type::size;
using index_type::erase;
//!Constructor. Takes a pointer to the
//!segment manager. Can throw
@@ -127,14 +143,18 @@ class iset_index
{ /*Does nothing, this intrusive index does not allocate memory;*/ }
iterator find(const compare_key_type&key)
{ return index_type::find(key, intrusive_key_value_less()); }
{ return index_type::find(key, less_function()); }
const_iterator find(const compare_key_type&key) const
{ return index_type::find(key, intrusive_key_value_less()); }
{ return index_type::find(key, less_function()); }
std::pair<iterator, bool>insert_check
(const compare_key_type&key, insert_commit_data &commit_data)
{ return index_type::insert_check(key, intrusive_key_value_less(), commit_data); }
(const compare_key_type &key, insert_commit_data &commit_data)
{ return index_type::insert_check(key, less_function(), commit_data); }
iterator insert_commit
(const compare_key_type &, void*, index_data_t&v, insert_commit_data& commit_data)
{ return index_type::insert_commit(v, commit_data); }
};
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

View File

@@ -146,7 +146,7 @@ template <class MapConfig>
class iunordered_set_index
//Derive class from map specialization
: private iunordered_set_index_aux<MapConfig>::allocator_holder
, public iunordered_set_index_aux<MapConfig>::index_t
, private iunordered_set_index_aux<MapConfig>::index_t
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef iunordered_set_index_aux<MapConfig> index_aux;
@@ -172,6 +172,7 @@ class iunordered_set_index
typedef typename index_type::bucket_traits bucket_traits;
typedef typename index_type::size_type size_type;
typedef typename index_type::difference_type difference_type;
typedef value_type index_data_t;
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
private:
@@ -260,6 +261,11 @@ class iunordered_set_index
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
using index_type::begin;
using index_type::end;
using index_type::size;
using index_type::erase;
//!Constructor. Takes a pointer to the
//!segment manager. Can throw
iunordered_set_index(segment_manager_base *mngr)
@@ -346,7 +352,8 @@ class iunordered_set_index
(const compare_key_type&key, insert_commit_data &commit_data)
{ return index_type::insert_check(key, hash_function(), equal_function(), commit_data); }
iterator insert_commit(value_type &val, insert_commit_data &commit_data)
iterator insert_commit
(const compare_key_type &, void *, index_data_t &val, insert_commit_data& commit_data)
{
iterator it = index_type::insert_commit(val, commit_data);
size_type cur_size = this->size();

View File

@@ -62,16 +62,29 @@ struct map_index_aux
template <class MapConfig>
class map_index
//Derive class from map specialization
: public ipcdetail::map_index_aux<MapConfig>::index_t
: private ipcdetail::map_index_aux<MapConfig>::index_t
{
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
typedef ipcdetail::map_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t base_type;
typedef ipcdetail::map_index_aux<MapConfig> index_aux;
typedef typename index_aux::index_t base_type;
typedef typename MapConfig::
segment_manager_base segment_manager_base;
segment_manager_base segment_manager_base;
typedef typename base_type::key_type key_type;
#endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
public:
using base_type::begin;
using base_type::end;
using base_type::size;
using base_type::erase;
typedef typename base_type::iterator iterator;
typedef typename base_type::const_iterator const_iterator;
typedef typename base_type::value_type value_type;
typedef typename MapConfig::compare_key_type compare_key_type;
typedef iterator insert_commit_data;
typedef iterator index_data_t;
//!Constructor. Takes a pointer to the
//!segment manager. Can throw
map_index(segment_manager_base *segment_mngr)
@@ -87,6 +100,27 @@ class map_index
//!unused memory.
void shrink_to_fit()
{ base_type::get_stored_allocator().deallocate_free_blocks(); }
std::pair<iterator, bool> insert_check
(const compare_key_type& key, insert_commit_data& )
{
std::pair<iterator, bool> r;
r.first = this->base_type::find(key_type(key.str(), key.len()));
r.second = r.first == this->base_type::end();
return r;
}
iterator insert_commit
(const compare_key_type &k, void *context, index_data_t &index_data, insert_commit_data& )
{
//Now commit the insertion using previous context data
typedef typename base_type::mapped_type mapped_type;
iterator it = this->base_type::insert(value_type(key_type(k.str(), k.len()), mapped_type(context))).first;
return (index_data = it);
}
iterator find(const compare_key_type& k)
{ return this->base_type::find(key_type(k.str(), k.len())); }
};
#if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)

View File

@@ -479,12 +479,10 @@ class segment_manager
BOOST_ASSERT(!name.is_anonymous());
if(name.is_unique()){
return this->priv_generic_named_destroy<T, char>
( typeid(T).name(), m_header.m_unique_index, is_intrusive_t());
return this->priv_generic_named_destroy<T, char>(typeid(T).name(), m_header.m_unique_index);
}
else{
return this->priv_generic_named_destroy<T, CharType>
( name.get(), m_header.m_named_index, is_intrusive_t());
return this->priv_generic_named_destroy<T, CharType>(name.get(), m_header.m_named_index);
}
}
@@ -654,11 +652,11 @@ class segment_manager
}
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());
(pr, unique_type, typeid(object_type).name(), num, try2find, dothrow, m_header.m_unique_index);
}
else{
return this->priv_generic_named_construct
(pr, named_type, name, num, try2find, dothrow, m_header.m_named_index, is_intrusive_t());
(pr, named_type, name, num, try2find, dothrow, m_header.m_named_index);
}
}
@@ -830,9 +828,10 @@ class segment_manager
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
size_type &length, bool use_lock)
{
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
typedef typename index_type_t::iterator index_it;
typedef typename ipcdetail::compare_key<index_type_t>::type compare_key_t;
typedef IndexType<ipcdetail::index_config
<CharT, MemoryAlgorithm> > index_t;
typedef typename index_t::iterator index_it;
typedef typename index_t::compare_key_type compare_key_t;
//-------------------------------
scoped_lock<rmutex> guard(priv_get_lock(use_lock));
@@ -866,10 +865,11 @@ class segment_manager
,ipcdetail::true_ is_node_index)
{
(void)is_node_index;
typedef typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator index_it;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
typedef typename index_t::index_data_t index_data_t;
index_it *ihdr = block_header_t::template to_first_header<index_it>(block_header);
return this->priv_generic_named_destroy_impl<T, CharT>(*ihdr, index);
index_data_t *si = priv_index_header_from_block<index_t>(block_header, is_intrusive_t());
return this->priv_generic_named_destroy_impl<T, CharT>(*si, index);
}
template <class T, class CharT>
@@ -880,73 +880,24 @@ class segment_manager
{
(void)is_node_index;
CharT *name = static_cast<CharT*>(block_header->template name<CharT>());
return this->priv_generic_named_destroy<T, CharT>(name, index, is_intrusive_t());
return this->priv_generic_named_destroy<T, CharT>(name, index);
}
template <class T, class CharT>
bool priv_generic_named_destroy(const CharT *name,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::true_ is_intrusive)
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
{
(void)is_intrusive;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
typedef typename index_type_t::iterator index_it;
typedef typename index_type_t::value_type intrusive_value_type;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
typedef typename index_t::iterator index_it;
typedef typename index_t::compare_key_type compare_key_t;
//-------------------------------
scoped_lock<rmutex> guard(m_header);
//-------------------------------
//Find name in index
ipcdetail::intrusive_compare_key<CharT> key
(name, std::char_traits<CharT>::length(name));
compare_key_t key(name, std::char_traits<CharT>::length(name));
index_it it = index.find(key);
//If not found, return false
if(it == index.end()){
//This name is not present in the index, wrong pointer or name!
//BOOST_ASSERT(0);
return false;
}
block_header_t *ctrl_data = priv_block_header_from_it(it, is_intrusive);
intrusive_value_type *iv = intrusive_value_type::get_intrusive_value_type(ctrl_data);
void *memory = iv;
//Sanity check
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();
this->deallocate(memory);
return true;
}
template <class T, class CharT>
bool priv_generic_named_destroy(const CharT *name,
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
ipcdetail::false_ is_intrusive_index)
{
(void)is_intrusive_index;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > char_aware_index_type;
typedef typename char_aware_index_type::iterator index_it;
typedef typename char_aware_index_type::key_type key_type;
//-------------------------------
scoped_lock<rmutex> guard(m_header);
//-------------------------------
//Try to find the name in the index
index_it it = index.find(key_type (name,
std::char_traits<CharT>::length(name)));
//If not found, return false
if(it == index.end()){
//This name is not present in the index, wrong pointer or name!
@@ -961,29 +912,23 @@ class segment_manager
(const typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator &it,
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;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
typedef typename index_t::index_data_t index_data_t;
//Get allocation parameters
block_header_t *ctrl_data = priv_block_header_from_it(it, is_intrusive_t());
char *stored_name = static_cast<char*>(static_cast<void*>(const_cast<CharT*>(it->first.name())));
(void)stored_name;
//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);
void *memory;
BOOST_IF_CONSTEXPR(is_node_index_t::value){
index_it *ihdr = block_header_t::template
to_first_header<index_it>(ctrl_data);
ihdr->~index_it();
BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value){
index_data_t*ihdr = priv_index_header_from_block<index_t>(ctrl_data, is_intrusive_t());
ihdr->~index_data_t();
memory = ihdr;
}
else{
@@ -993,7 +938,7 @@ class segment_manager
//Call destructors and free memory
priv_destroy_n(static_cast<T*>(ctrl_data->value()), ctrl_data->m_value_bytes/sizeof(T));
//Destroy the header
//Destroy the headers
ctrl_data->~block_header_t();
this->deallocate(memory);
@@ -1003,7 +948,7 @@ class segment_manager
template<class IndexIt>
static block_header_t* priv_block_header_from_it(IndexIt it, ipcdetail::true_) //is_intrusive
{
return it->get_block_header();
return block_header_t::from_first_header(&*it);
}
template<class IndexIt>
@@ -1012,12 +957,26 @@ class segment_manager
return static_cast<block_header_t*>(ipcdetail::to_raw_pointer(it->second.m_ptr));
}
template<class IndexT>
static typename IndexT::index_data_t * priv_index_header_from_block(block_header_t *bh, ipcdetail::true_) //is_intrusive
{
return IndexT::index_data_t::get_intrusive_value_type(bh);
}
template<class IndexT>
static typename IndexT::index_data_t * priv_index_header_from_block(block_header_t* bh, ipcdetail::false_) //!is_intrusive
{
return block_header_t::template to_first_header
<typename IndexT::index_data_t>(bh);
}
//!Generic named new function for
//!named functions
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)
IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
{
(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;
@@ -1028,8 +987,11 @@ class segment_manager
, sizeof(CharT)
, namelen);
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
typedef typename index_type_t::iterator index_it;
typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
typedef typename index_t::iterator index_it;
typedef typename index_t::compare_key_type compare_key_t;
typedef typename index_t::insert_commit_data commit_data_t;
typedef typename index_t::index_data_t index_data_t;
//-------------------------------
scoped_lock<rmutex> guard(m_header);
@@ -1040,13 +1002,11 @@ class segment_manager
//contain the name and the user buffer.
index_it existing_it;
bool found = false;
typedef typename index_type_t::value_type value_type;
typename index_type_t::insert_commit_data commit_data;
commit_data_t commit_data;
BOOST_INTERPROCESS_TRY{
typedef std::pair<index_it, bool> index_ib;
ipcdetail::intrusive_compare_key<CharT> key(name, namelen);
index_ib insert_ret = index.insert_check(key, commit_data);
index_ib insert_ret = index.insert_check(compare_key_t(name, namelen), commit_data);
existing_it = insert_ret.first;
found = !insert_ret.second;
}
@@ -1061,110 +1021,7 @@ class segment_manager
//If found and this is find or construct, return data, error otherwise
if(found){
if(try2find){
return static_cast<object_type*>(priv_block_header_from_it(existing_it, is_intrusive)->value());
}
return ipcdetail::null_or_already_exists<object_type>(dothrow);
}
//Allocates buffer for name + data, this can throw (it hurts)
void *buffer_ptr = this->allocate
(block_info.template total_size_with_header<value_type>(), nothrow<>::get());
//Check if there is enough memory
if (!buffer_ptr)
return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
//Now construct the intrusive hook plus the header
value_type* intrusive_hdr = ::new(buffer_ptr, boost_container_new_t()) value_type();
block_header_t * hdr = ::new(intrusive_hdr->get_block_header(), boost_container_new_t()) block_header_t(block_info);
void *ptr = hdr->value();
//Copy name to memory segment and insert data
CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
index_it it;
BOOST_INTERPROCESS_TRY{
//Now commit the insertion using previous context data
it = index.insert_commit(*intrusive_hdr, commit_data);
}
//Ignore exceptions
BOOST_INTERPROCESS_CATCH(...){
if(dothrow)
BOOST_INTERPROCESS_RETHROW
return 0;
}
BOOST_INTERPROCESS_CATCH_END
//Avoid constructions if constructor is trivial
//Build scoped ptr to avoid leaks with constructor exception
ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
(buffer_ptr, *static_cast<segment_manager_base_type*>(this));
//Initialize the node value_eraser to erase inserted node
//if something goes wrong. This will be executed *before*
//the memory allocation as the intrusive value is built in that
//memory
value_eraser<index_type_t> v_eraser(index, it);
//Construct array, this can throw
pr.construct_n(ptr, num);
//Release rollbacks since construction was successful
v_eraser.release();
mem.release();
return static_cast<object_type*>(ptr);
}
//!Generic named new function for
//!named functions
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(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;
//-------------------------------
scoped_lock<rmutex> guard(m_header);
//-------------------------------
//First, we want to know if the key is already present before
//we allocate any memory, and if the key is not present, we
//want to allocate all memory in a single buffer that will
//contain the name and the user buffer.
index_it existing_it;
bool found = false;
typedef typename index_type_t::value_type value_type;
BOOST_INTERPROCESS_TRY{
typedef typename index_type_t::key_type key_type;
existing_it = index.find(key_type(name, namelen));
found = existing_it != index.end();
}
//Ignore exceptions
BOOST_INTERPROCESS_CATCH(...){
if(dothrow)
BOOST_INTERPROCESS_RETHROW
return 0;
}
BOOST_INTERPROCESS_CATCH_END
//If found and this is find or construct, return data, error otherwise
if(found){
if(try2find){
return static_cast<object_type*>(priv_block_header_from_it(existing_it, is_intrusive)->value());
return static_cast<object_type*>(priv_block_header_from_it(existing_it, is_intrusive_t())->value());
}
return ipcdetail::null_or_already_exists<object_type>(dothrow);
}
@@ -1174,12 +1031,12 @@ class segment_manager
block_header_t * hdr;
//Allocate and construct the headers
BOOST_IF_CONSTEXPR(is_node_index_t::value){
size_type total_size = block_info.template total_size_with_header<index_it>();
BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value){
size_type total_size = block_info.template total_size_with_header<index_data_t>();
buffer_ptr = this->allocate(total_size, nothrow<>::get());
if(!buffer_ptr)
return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
hdr = block_header_t::template from_first_header<index_it>(static_cast<index_it*>(buffer_ptr));
hdr = block_header_t::template from_first_header<index_data_t>(static_cast<index_data_t*>(buffer_ptr));
}
else{
buffer_ptr = this->allocate(block_info.total_size(), nothrow<>::get());
@@ -1195,7 +1052,7 @@ class segment_manager
ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
(buffer_ptr, *static_cast<segment_manager_base_type*>(this));
void *ptr = hdr->value();
void *ptr = hdr->value();
//Copy name to memory segment and insert data
CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
@@ -1203,12 +1060,13 @@ class segment_manager
index_it it;
BOOST_INTERPROCESS_TRY{
//Now commit the insertion using previous context data
typedef typename index_type_t::mapped_type mapped_type;
typedef typename index_type_t::key_type key_type;
it = index.insert(value_type(key_type(name_ptr, namelen), mapped_type(hdr))).first;
BOOST_IF_CONSTEXPR(is_node_index_t::value) {
::new(buffer_ptr, boost_container_new_t()) index_it(it);
BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value) {
index_data_t* index_data = ::new(buffer_ptr, boost_container_new_t()) index_data_t();
it = index.insert_commit(compare_key_t(name_ptr, namelen), hdr, *index_data, commit_data);
}
else{
index_data_t id;
it = index.insert_commit(compare_key_t(name_ptr, namelen), hdr, id, commit_data);
}
}
//Ignore exceptions
@@ -1221,7 +1079,7 @@ class segment_manager
//Initialize the node value_eraser to erase inserted node
//if something goes wrong
value_eraser<index_type_t> v_eraser(index, it);
value_eraser<index_t> v_eraser(index, it);
//Construct array, this can throw
pr.construct_n(ptr, num);