mirror of
https://github.com/boostorg/interprocess.git
synced 2026-01-19 16:22:19 +00:00
Refactor quasi-duplicated priv_generic_named_destroy and priv_generic_named_construct implementations.
This commit is contained in:
@@ -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>(); }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user