1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366 |
- //////////////////////////////////////////////////////////////////////////////
- //
- // (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_SEGMENT_MANAGER_HPP
- #define BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
- #if (defined _MSC_VER) && (_MSC_VER >= 1200)
- # pragma once
- #endif
- #include <boost/interprocess/detail/config_begin.hpp>
- #include <boost/interprocess/detail/workaround.hpp>
- #include <boost/detail/no_exceptions_support.hpp>
- #include <boost/interprocess/detail/type_traits.hpp>
- #include <boost/interprocess/detail/transform_iterator.hpp>
- #include <boost/interprocess/detail/mpl.hpp>
- #include <boost/interprocess/detail/segment_manager_helper.hpp>
- #include <boost/interprocess/detail/named_proxy.hpp>
- #include <boost/interprocess/detail/utilities.hpp>
- #include <boost/interprocess/offset_ptr.hpp>
- #include <boost/interprocess/indexes/iset_index.hpp>
- #include <boost/interprocess/exceptions.hpp>
- #include <boost/interprocess/allocators/allocator.hpp>
- #include <boost/interprocess/smart_ptr/deleter.hpp>
- #include <boost/move/move.hpp>
- #include <boost/interprocess/sync/scoped_lock.hpp>
- #include <cstddef> //std::size_t
- #include <string> //char_traits
- #include <new> //std::nothrow
- #include <utility> //std::pair
- #include <boost/assert.hpp>
- #ifndef BOOST_NO_EXCEPTIONS
- #include <exception>
- #endif
- //!\file
- //!Describes the object placed in a memory segment that provides
- //!named object allocation capabilities for single-segment and
- //!multi-segment allocations.
- namespace boost{
- namespace interprocess{
- //!This object is the public base class of segment manager.
- //!This class only depends on the memory allocation algorithm
- //!and implements all the allocation features not related
- //!to named or unique objects.
- //!
- //!Storing a reference to segment_manager forces
- //!the holder class to be dependent on index types and character types.
- //!When such dependence is not desirable and only anonymous and raw
- //!allocations are needed, segment_manager_base is the correct answer.
- template<class MemoryAlgorithm>
- class segment_manager_base
- : private MemoryAlgorithm
- {
- public:
- typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
- typedef typename MemoryAlgorithm::void_pointer void_pointer;
- typedef typename MemoryAlgorithm::mutex_family mutex_family;
- typedef MemoryAlgorithm memory_algorithm;
- /// @cond
- //Experimental. Don't use
- typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain;
- typedef typename MemoryAlgorithm::difference_type difference_type;
- typedef typename MemoryAlgorithm::size_type size_type;
- /// @endcond
- //!This constant indicates the payload size
- //!associated with each allocation of the memory algorithm
- static const size_type PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation;
- //!Constructor of the segment_manager_base
- //!
- //!"size" is the size of the memory segment where
- //!the basic segment manager is being constructed.
- //!
- //!"reserved_bytes" is the number of bytes
- //!after the end of the memory algorithm object itself
- //!that the memory algorithm will exclude from
- //!dynamic allocation
- //!
- //!Can throw
- segment_manager_base(size_type sz, size_type reserved_bytes)
- : MemoryAlgorithm(sz, reserved_bytes)
- {
- BOOST_ASSERT((sizeof(segment_manager_base<MemoryAlgorithm>) == sizeof(MemoryAlgorithm)));
- }
- //!Returns the size of the memory
- //!segment
- size_type get_size() const
- { return MemoryAlgorithm::get_size(); }
- //!Returns the number of free bytes of the memory
- //!segment
- size_type get_free_memory() const
- { return MemoryAlgorithm::get_free_memory(); }
- //!Obtains the minimum size needed by
- //!the segment manager
- static size_type get_min_size (size_type size)
- { return MemoryAlgorithm::get_min_size(size); }
- //!Allocates nbytes bytes. This function is only used in
- //!single-segment management. Never throws
- void * allocate (size_type nbytes, std::nothrow_t)
- { return MemoryAlgorithm::allocate(nbytes); }
- /// @cond
- //Experimental. Dont' use.
- //!Allocates n_elements of elem_bytes bytes.
- //!Throws bad_alloc on failure. chain.size() is not increased on failure.
- void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
- {
- size_type prev_size = chain.size();
- MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain);
- if(!elem_bytes || chain.size() == prev_size){
- throw bad_alloc();
- }
- }
- //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
- //!Throws bad_alloc on failure. chain.size() is not increased on failure.
- void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
- {
- size_type prev_size = chain.size();
- MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, chain);
- if(!sizeof_element || chain.size() == prev_size){
- throw bad_alloc();
- }
- }
- //!Allocates n_elements of elem_bytes bytes.
- //!Non-throwing version. chain.size() is not increased on failure.
- void allocate_many(std::nothrow_t, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
- { MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); }
- //!Allocates n_elements, each one of
- //!element_lengths[i]*sizeof_element bytes.
- //!Non-throwing version. chain.size() is not increased on failure.
- void allocate_many(std::nothrow_t, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
- { MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, chain); }
- //!Deallocates all elements contained in chain.
- //!Never throws.
- void deallocate_many(multiallocation_chain &chain)
- { MemoryAlgorithm::deallocate_many(chain); }
- /// @endcond
- //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc
- //!on failure
- void * allocate(size_type nbytes)
- {
- void * ret = MemoryAlgorithm::allocate(nbytes);
- if(!ret)
- throw bad_alloc();
- return ret;
- }
- //!Allocates nbytes bytes. This function is only used in
- //!single-segment management. Never throws
- void * allocate_aligned (size_type nbytes, size_type alignment, std::nothrow_t)
- { return MemoryAlgorithm::allocate_aligned(nbytes, alignment); }
- //!Allocates nbytes bytes. This function is only used in
- //!single-segment management. Throws bad_alloc when fails
- void * allocate_aligned(size_type nbytes, size_type alignment)
- {
- void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
- if(!ret)
- throw bad_alloc();
- return ret;
- }
- template<class T>
- std::pair<T *, bool>
- allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
- size_type preferred_size,size_type &received_size,
- T *reuse_ptr = 0)
- {
- std::pair<T *, bool> ret = MemoryAlgorithm::allocation_command
- ( command | boost::interprocess::nothrow_allocation, limit_size, preferred_size, received_size
- , reuse_ptr);
- if(!(command & boost::interprocess::nothrow_allocation) && !ret.first)
- throw bad_alloc();
- return ret;
- }
- std::pair<void *, bool>
- raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects,
- size_type preferred_objects,size_type &received_objects,
- void *reuse_ptr = 0, size_type sizeof_object = 1)
- {
- std::pair<void *, bool> ret = MemoryAlgorithm::raw_allocation_command
- ( command | boost::interprocess::nothrow_allocation, limit_objects, preferred_objects, received_objects
- , reuse_ptr, sizeof_object);
- if(!(command & boost::interprocess::nothrow_allocation) && !ret.first)
- throw bad_alloc();
- return ret;
- }
- //!Deallocates the bytes allocated with allocate/allocate_many()
- //!pointed by addr
- void deallocate (void *addr)
- { MemoryAlgorithm::deallocate(addr); }
- //!Increases managed memory in extra_size bytes more. This only works
- //!with single-segment management.
- void grow(size_type extra_size)
- { MemoryAlgorithm::grow(extra_size); }
- //!Decreases managed memory to the minimum. This only works
- //!with single-segment management.
- void shrink_to_fit()
- { MemoryAlgorithm::shrink_to_fit(); }
- //!Returns the result of "all_memory_deallocated()" function
- //!of the used memory algorithm
- bool all_memory_deallocated()
- { return MemoryAlgorithm::all_memory_deallocated(); }
- //!Returns the result of "check_sanity()" function
- //!of the used memory algorithm
- bool check_sanity()
- { return MemoryAlgorithm::check_sanity(); }
- //!Writes to zero free memory (memory not yet allocated)
- //!of the memory algorithm
- void zero_free_memory()
- { MemoryAlgorithm::zero_free_memory(); }
- //!Returns the size of the buffer previously allocated pointed by ptr
- size_type size(const void *ptr) const
- { return MemoryAlgorithm::size(ptr); }
- /// @cond
- 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);
- //Allocate memory
- void *ptr_struct = this->allocate(block_info.total_size(), std::nothrow_t());
- //Check if there is enough memory
- if(!ptr_struct){
- if(dothrow){
- throw bad_alloc();
- }
- else{
- return 0;
- }
- }
- //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) block_header_t(block_info);
- void *ptr = 0; //avoid gcc warning
- ptr = hdr->value();
- //Now call constructors
- ipcdetail::array_construct(ptr, num, table);
- //All constructors successful, we don't want erase memory
- 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);
- //-------------------------------
- if(ctrl_data->alloc_type() != anonymous_type){
- //This is not an anonymous object, the pointer is wrong!
- BOOST_ASSERT(0);
- }
- //Call destructors and free memory
- //Build scoped ptr to avoid leaks with destructor exception
- std::size_t destroyed = 0;
- table.destroy_n(const_cast<void*>(object), ctrl_data->m_value_bytes/table.size, destroyed);
- this->deallocate(ctrl_data);
- }
- /// @endcond
- };
- //!This object is placed in the beginning of memory segment and
- //!implements the allocation (named or anonymous) of portions
- //!of the segment. This object contains two indexes that
- //!maintain an association between a name and a portion of the segment.
- //!
- //!The first index contains the mappings for normal named objects using the
- //!char type specified in the template parameter.
- //!
- //!The second index contains the association for unique instances. The key will
- //!be the const char * returned from type_info.name() function for the unique
- //!type to be constructed.
- //!
- //!segment_manager<CharType, MemoryAlgorithm, IndexType> inherits publicly
- //!from segment_manager_base<MemoryAlgorithm> and inherits from it
- //!many public functions related to anonymous object and raw memory allocation.
- //!See segment_manager_base reference to know about those functions.
- template<class CharType
- ,class MemoryAlgorithm
- ,template<class IndexConfig> class IndexType>
- class segment_manager
- : public segment_manager_base<MemoryAlgorithm>
- {
- /// @cond
- //Non-copyable
- segment_manager();
- segment_manager(const segment_manager &);
- segment_manager &operator=(const segment_manager &);
- typedef segment_manager_base<MemoryAlgorithm> Base;
- /// @endcond
- public:
- typedef MemoryAlgorithm memory_algorithm;
- typedef typename Base::void_pointer void_pointer;
- typedef typename Base::size_type size_type;
- typedef typename Base::difference_type difference_type;
- typedef CharType char_type;
- typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
- static const size_type PayloadPerAllocation = Base::PayloadPerAllocation;
- /// @cond
- private:
- typedef ipcdetail::block_header<size_type> block_header_t;
- typedef ipcdetail::index_config<CharType, MemoryAlgorithm> index_config_named;
- typedef ipcdetail::index_config<char, MemoryAlgorithm> index_config_unique;
- typedef IndexType<index_config_named> index_type;
- typedef ipcdetail::bool_<is_intrusive_index<index_type>::value > is_intrusive_t;
- typedef ipcdetail::bool_<is_node_index<index_type>::value> is_node_index_t;
- public:
- typedef IndexType<index_config_named> named_index_t;
- typedef IndexType<index_config_unique> unique_index_t;
- typedef ipcdetail::char_ptr_holder<CharType> char_ptr_holder_t;
- typedef ipcdetail::segment_manager_iterator_transform
- <typename named_index_t::const_iterator
- ,is_intrusive_index<index_type>::value> named_transform;
- typedef ipcdetail::segment_manager_iterator_transform
- <typename unique_index_t::const_iterator
- ,is_intrusive_index<index_type>::value> unique_transform;
- /// @endcond
- typedef typename Base::mutex_family mutex_family;
- typedef transform_iterator
- <typename named_index_t::const_iterator, named_transform> const_named_iterator;
- typedef transform_iterator
- <typename unique_index_t::const_iterator, unique_transform> const_unique_iterator;
- /// @cond
- //!Constructor proxy object definition helper class
- template<class T>
- struct construct_proxy
- {
- typedef ipcdetail::named_proxy<segment_manager, T, false> type;
- };
- //!Constructor proxy object definition helper class
- template<class T>
- struct construct_iter_proxy
- {
- typedef ipcdetail::named_proxy<segment_manager, T, true> type;
- };
- /// @endcond
- //!Constructor of the segment manager
- //!"size" is the size of the memory segment where
- //!the segment manager is being constructed.
- //!Can throw
- explicit segment_manager(size_type segment_size)
- : Base(segment_size, priv_get_reserved_bytes())
- , m_header(static_cast<Base*>(get_this_pointer()))
- {
- (void) anonymous_instance; (void) unique_instance;
- BOOST_ASSERT(static_cast<const void*>(this) == static_cast<const void*>(static_cast<Base*>(this)));
- }
- //!Tries to find a previous named allocation. Returns the address
- //!and the object count. On failure the first member of the
- //!returned pair is 0.
- template <class T>
- std::pair<T*, size_type> find (const CharType* name)
- { return this->priv_find_impl<T>(name, true); }
- //!Tries to find a previous unique allocation. Returns the address
- //!and the object count. On failure the first member of the
- //!returned pair is 0.
- template <class T>
- std::pair<T*, size_type> find (const ipcdetail::unique_instance_t* name)
- { return this->priv_find_impl<T>(name, true); }
- //!Tries to find a previous named allocation. Returns the address
- //!and the object count. On failure the first member of the
- //!returned pair is 0. This search is not mutex-protected!
- template <class T>
- std::pair<T*, size_type> find_no_lock (const CharType* name)
- { return this->priv_find_impl<T>(name, false); }
- //!Tries to find a previous unique allocation. Returns the address
- //!and the object count. On failure the first member of the
- //!returned pair is 0. This search is not mutex-protected!
- template <class T>
- std::pair<T*, size_type> find_no_lock (const ipcdetail::unique_instance_t* name)
- { return this->priv_find_impl<T>(name, false); }
- //!Returns throwing "construct" proxy
- //!object
- template <class T>
- typename construct_proxy<T>::type
- construct(char_ptr_holder_t name)
- { return typename construct_proxy<T>::type (this, name, false, true); }
- //!Returns throwing "search or construct" proxy
- //!object
- template <class T>
- typename construct_proxy<T>::type find_or_construct(char_ptr_holder_t name)
- { return typename construct_proxy<T>::type (this, name, true, true); }
- //!Returns no throwing "construct" proxy
- //!object
- template <class T>
- typename construct_proxy<T>::type
- construct(char_ptr_holder_t name, std::nothrow_t)
- { return typename construct_proxy<T>::type (this, name, false, false); }
- //!Returns no throwing "search or construct"
- //!proxy object
- template <class T>
- typename construct_proxy<T>::type
- find_or_construct(char_ptr_holder_t name, std::nothrow_t)
- { return typename construct_proxy<T>::type (this, name, true, false); }
- //!Returns throwing "construct from iterators" proxy object
- template <class T>
- typename construct_iter_proxy<T>::type
- construct_it(char_ptr_holder_t name)
- { return typename construct_iter_proxy<T>::type (this, name, false, true); }
- //!Returns throwing "search or construct from iterators"
- //!proxy object
- template <class T>
- typename construct_iter_proxy<T>::type
- find_or_construct_it(char_ptr_holder_t name)
- { return typename construct_iter_proxy<T>::type (this, name, true, true); }
- //!Returns no throwing "construct from iterators"
- //!proxy object
- template <class T>
- typename construct_iter_proxy<T>::type
- construct_it(char_ptr_holder_t name, std::nothrow_t)
- { return typename construct_iter_proxy<T>::type (this, name, false, false); }
- //!Returns no throwing "search or construct from iterators"
- //!proxy object
- template <class T>
- typename construct_iter_proxy<T>::type
- find_or_construct_it(char_ptr_holder_t name, std::nothrow_t)
- { return typename construct_iter_proxy<T>::type (this, name, true, false); }
- //!Calls object function blocking recursive interprocess_mutex and guarantees that
- //!no new named_alloc or destroy will be executed by any process while
- //!executing the object function call*/
- template <class Func>
- void atomic_func(Func &f)
- { scoped_lock<rmutex> guard(m_header); f(); }
- //!Tries to calls a functor guaranteeing that no new construction, search or
- //!destruction will be executed by any process while executing the object
- //!function call. If the atomic function can't be immediatelly executed
- //!because the internal mutex is already locked, returns false.
- //!If the functor throws, this function throws.
- template <class Func>
- bool try_atomic_func(Func &f)
- {
- scoped_lock<rmutex> guard(m_header, try_to_lock);
- if(guard){
- f();
- return true;
- }
- else{
- return false;
- }
- }
- //!Destroys a previously created unique instance.
- //!Returns false if the object was not present.
- template <class T>
- bool destroy(const ipcdetail::unique_instance_t *)
- {
- ipcdetail::placement_destroy<T> dtor;
- return this->priv_generic_named_destroy<char>
- (typeid(T).name(), m_header.m_unique_index, dtor, is_intrusive_t());
- }
- //!Destroys the named object with
- //!the given name. Returns false if that object can't be found.
- template <class T>
- bool destroy(const CharType *name)
- {
- ipcdetail::placement_destroy<T> dtor;
- return this->priv_generic_named_destroy<CharType>
- (name, m_header.m_named_index, dtor, is_intrusive_t());
- }
- //!Destroys an anonymous, unique or named object
- //!using it's address
- 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);
- }
- //!Returns the name of an object created with construct/find_or_construct
- //!functions. Does not throw
- template<class T>
- static const CharType *get_instance_name(const T *ptr)
- { return priv_get_instance_name(block_header_t::block_header_from_value(ptr)); }
- //!Returns the length of an object created with construct/find_or_construct
- //!functions. Does not throw.
- template<class T>
- static size_type get_instance_length(const T *ptr)
- { return priv_get_instance_length(block_header_t::block_header_from_value(ptr), sizeof(T)); }
- //!Returns is the the name of an object created with construct/find_or_construct
- //!functions. Does not throw
- template<class T>
- static instance_type get_instance_type(const T *ptr)
- { return priv_get_instance_type(block_header_t::block_header_from_value(ptr)); }
- //!Preallocates needed index resources to optimize the
- //!creation of "num" named objects in the managed memory segment.
- //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
- void reserve_named_objects(size_type num)
- {
- //-------------------------------
- scoped_lock<rmutex> guard(m_header);
- //-------------------------------
- m_header.m_named_index.reserve(num);
- }
- //!Preallocates needed index resources to optimize the
- //!creation of "num" unique objects in the managed memory segment.
- //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
- void reserve_unique_objects(size_type num)
- {
- //-------------------------------
- scoped_lock<rmutex> guard(m_header);
- //-------------------------------
- m_header.m_unique_index.reserve(num);
- }
- //!Calls shrink_to_fit in both named and unique object indexes
- //!to try to free unused memory from those indexes.
- void shrink_to_fit_indexes()
- {
- //-------------------------------
- scoped_lock<rmutex> guard(m_header);
- //-------------------------------
- m_header.m_named_index.shrink_to_fit();
- m_header.m_unique_index.shrink_to_fit();
- }
- //!Returns the number of named objects stored in
- //!the segment.
- size_type get_num_named_objects()
- {
- //-------------------------------
- scoped_lock<rmutex> guard(m_header);
- //-------------------------------
- return m_header.m_named_index.size();
- }
- //!Returns the number of unique objects stored in
- //!the segment.
- size_type get_num_unique_objects()
- {
- //-------------------------------
- scoped_lock<rmutex> guard(m_header);
- //-------------------------------
- return m_header.m_unique_index.size();
- }
- //!Obtains the minimum size needed by the
- //!segment manager
- static size_type get_min_size()
- { return Base::get_min_size(priv_get_reserved_bytes()); }
- //!Returns a constant iterator to the beginning of the information about
- //!the named allocations performed in this segment manager
- const_named_iterator named_begin() const
- {
- return make_transform_iterator
- (m_header.m_named_index.begin(), named_transform());
- }
- //!Returns a constant iterator to the end of the information about
- //!the named allocations performed in this segment manager
- const_named_iterator named_end() const
- {
- return make_transform_iterator
- (m_header.m_named_index.end(), named_transform());
- }
- //!Returns a constant iterator to the beginning of the information about
- //!the unique allocations performed in this segment manager
- const_unique_iterator unique_begin() const
- {
- return make_transform_iterator
- (m_header.m_unique_index.begin(), unique_transform());
- }
- //!Returns a constant iterator to the end of the information about
- //!the unique allocations performed in this segment manager
- const_unique_iterator unique_end() const
- {
- return make_transform_iterator
- (m_header.m_unique_index.end(), unique_transform());
- }
- //!This is the default allocator to allocate types T
- //!from this managed segment
- template<class T>
- struct allocator
- {
- typedef boost::interprocess::allocator<T, segment_manager> type;
- };
- //!Returns an instance of the default allocator for type T
- //!initialized that allocates memory from this segment manager.
- template<class T>
- typename allocator<T>::type
- get_allocator()
- { return typename allocator<T>::type(this); }
- //!This is the default deleter to delete types T
- //!from this managed segment.
- template<class T>
- struct deleter
- {
- typedef boost::interprocess::deleter<T, segment_manager> type;
- };
- //!Returns an instance of the default allocator for type T
- //!initialized that allocates memory from this segment manager.
- template<class T>
- typename deleter<T>::type
- get_deleter()
- { return typename deleter<T>::type(this); }
- /// @cond
- //!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)
- {
- return static_cast<T*>
- (priv_generic_construct(name, num, try2find, dothrow, table));
- }
- private:
- //!Tries to find a previous named allocation. Returns the address
- //!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 CharType* name, bool lock)
- {
- //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);
- }
- else{
- ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, sz, is_intrusive_t(), lock);
- }
- return std::pair<T*, size_type>(static_cast<T*>(ret), sz);
- }
- //!Tries to find a previous unique allocation. Returns the address
- //!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)
- {
- 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);
- 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)
- {
- void *ret;
- //Security overflow check
- if(num > ((std::size_t)-1)/table.size){
- if(dothrow)
- throw bad_alloc();
- else
- return 0;
- }
- 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;
- }
- void priv_destroy_ptr(const void *ptr, ipcdetail::in_place_interface &dtor)
- {
- block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr, dtor.size, dtor.alignment);
- switch(ctrl_data->alloc_type()){
- case anonymous_type:
- this->prot_anonymous_destroy(ptr, dtor);
- break;
- case named_type:
- this->priv_generic_named_destroy<CharType>
- (ctrl_data, m_header.m_named_index, dtor, 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());
- break;
- default:
- //This type is unknown, bad pointer passed to this function!
- BOOST_ASSERT(0);
- break;
- }
- }
- //!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)
- {
- boost::interprocess::allocation_type type = ctrl_data->alloc_type();
- if(type != named_type){
- BOOST_ASSERT((type == anonymous_type && ctrl_data->m_num_char == 0) ||
- (type == unique_type && ctrl_data->m_num_char != 0) );
- return 0;
- }
- CharType *name = static_cast<CharType*>(ctrl_data->template name<CharType>());
- //Sanity checks
- BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharType));
- BOOST_ASSERT(ctrl_data->m_num_char == std::char_traits<CharType>::length(name));
- return name;
- }
- static size_type priv_get_instance_length(block_header_t *ctrl_data, size_type sizeofvalue)
- {
- //Get header
- BOOST_ASSERT((ctrl_data->value_bytes() %sizeofvalue) == 0);
- return ctrl_data->value_bytes()/sizeofvalue;
- }
- //!Returns is the the name of an object created with construct/find_or_construct
- //!functions. Does not throw
- static instance_type priv_get_instance_type(block_header_t *ctrl_data)
- {
- //Get header
- BOOST_ASSERT((instance_type)ctrl_data->alloc_type() < max_allocation_type);
- return (instance_type)ctrl_data->alloc_type();
- }
- static size_type priv_get_reserved_bytes()
- {
- //Get the number of bytes until the end of (*this)
- //beginning in the end of the Base base.
- return sizeof(segment_manager) - sizeof(Base);
- }
- template <class CharT>
- void *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;
- typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
- typedef ipcdetail::index_key<CharT, void_pointer> index_key_t;
- typedef typename index_type::iterator index_it;
- //-------------------------------
- scoped_lock<rmutex> guard(priv_get_lock(use_lock));
- //-------------------------------
- //Find name in index
- ipcdetail::intrusive_compare_key<CharT> key
- (name, std::char_traits<CharT>::length(name));
- index_it it = index.find(key);
- //Initialize return values
- void *ret_ptr = 0;
- length = 0;
- //If found, assign values
- if(it != index.end()){
- //Get header
- 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->sizeof_char() == sizeof(CharT));
- ret_ptr = ctrl_data->value();
- length = ctrl_data->m_value_bytes/table.size;
- }
- return ret_ptr;
- }
- template <class CharT>
- void *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;
- typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
- typedef typename index_type::key_type key_type;
- typedef typename index_type::iterator index_it;
- //-------------------------------
- scoped_lock<rmutex> guard(priv_get_lock(use_lock));
- //-------------------------------
- //Find name in index
- index_it it = index.find(key_type(name, std::char_traits<CharT>::length(name)));
- //Initialize return values
- void *ret_ptr = 0;
- length = 0;
- //If found, assign values
- if(it != index.end()){
- //Get header
- block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
- (ipcdetail::to_raw_pointer(it->second.m_ptr));
- //Sanity check
- BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
- BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT));
- ret_ptr = ctrl_data->value();
- length = ctrl_data->m_value_bytes/table.size;
- }
- return ret_ptr;
- }
- template <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)
- {
- (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);
- }
- template <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)
- {
- (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());
- }
- template <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)
- {
- (void)is_intrusive_index;
- typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
- typedef ipcdetail::index_key<CharT, void_pointer> index_key_t;
- typedef typename index_type::iterator index_it;
- typedef typename index_type::value_type intrusive_value_type;
- //-------------------------------
- scoped_lock<rmutex> guard(m_header);
- //-------------------------------
- //Find name in index
- ipcdetail::intrusive_compare_key<CharT> 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 = 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(sizeof(CharT) == ctrl_data->sizeof_char());
- //Erase node from index
- index.erase(it);
- //Destroy the headers
- ctrl_data->~block_header_t();
- iv->~intrusive_value_type();
- //Call destructors and free memory
- std::size_t destroyed;
- table.destroy_n(values, num, destroyed);
- this->deallocate(memory);
- return true;
- }
- template <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;
- typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
- typedef typename index_type::iterator index_it;
- typedef typename 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!
- //BOOST_ASSERT(0);
- return false;
- }
- return this->priv_generic_named_destroy_impl<CharT>(it, index, table);
- }
- template <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)
- {
- typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
- typedef typename index_type::iterator index_it;
- //Get allocation parameters
- block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
- (ipcdetail::to_raw_pointer(it->second.m_ptr));
- 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>()));
- BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
- //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
- to_first_header<index_it>(ctrl_data);
- ihdr->~index_it();
- memory = ihdr;
- }
- else{
- memory = ctrl_data;
- }
- //Call destructors and free memory
- std::size_t destroyed;
- table.destroy_n(values, num, destroyed);
- 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,
- 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 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
- typedef typename index_type::iterator index_it;
- typedef std::pair<index_it, bool> index_ib;
- //-------------------------------
- scoped_lock<rmutex> guard(m_header);
- //-------------------------------
- //Insert the node. This can throw.
- //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.
- //
- //Since equal_range(key) + insert(hint, value) approach is
- //quite inefficient in container implementations
- //(they re-test if the position is correct), I've chosen
- //to insert the node, do an ugly un-const cast and modify
- //the key (which is a smart pointer) to an equivalent one
- index_ib insert_ret;
- typename index_type::insert_commit_data commit_data;
- typedef typename index_type::value_type intrusive_value_type;
- BOOST_TRY{
- ipcdetail::intrusive_compare_key<CharT> key(name, namelen);
- insert_ret = index.insert_check(key, commit_data);
- }
- //Ignore exceptions
- BOOST_CATCH(...){
- if(dothrow)
- BOOST_RETHROW
- return 0;
- }
- BOOST_CATCH_END
- index_it it = insert_ret.first;
- //If found and this is find or construct, return data
- //else return null
- if(!insert_ret.second){
- if(try2find){
- return it->get_block_header()->value();
- }
- if(dothrow){
- throw interprocess_exception(already_exists_error);
- }
- else{
- return 0;
- }
- }
- //Allocates buffer for name + data, this can throw (it hurts)
- void *buffer_ptr;
- //Check if there is enough memory
- if(dothrow){
- buffer_ptr = this->allocate
- (block_info.template total_size_with_header<intrusive_value_type>());
- }
- else{
- buffer_ptr = this->allocate
- (block_info.template total_size_with_header<intrusive_value_type>(), std::nothrow_t());
- if(!buffer_ptr)
- return 0;
- }
- //Now construct the intrusive hook plus the header
- intrusive_value_type * intrusive_hdr = new(buffer_ptr) intrusive_value_type();
- block_header_t * hdr = new(intrusive_hdr->get_block_header())block_header_t(block_info);
- void *ptr = 0; //avoid gcc warning
- 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);
- BOOST_TRY{
- //Now commit the insertion using previous context data
- it = index.insert_commit(*intrusive_hdr, commit_data);
- }
- //Ignore exceptions
- BOOST_CATCH(...){
- if(dothrow)
- BOOST_RETHROW
- return 0;
- }
- BOOST_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> v_eraser(index, it);
- //Construct array, this can throw
- ipcdetail::array_construct(ptr, num, table);
- //Release rollbacks since construction was successful
- v_eraser.release();
- mem.release();
- return 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,
- IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
- ipcdetail::false_ 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 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type;
- typedef typename index_type::key_type key_type;
- typedef typename index_type::mapped_type mapped_type;
- typedef typename index_type::value_type value_type;
- typedef typename index_type::iterator index_it;
- typedef std::pair<index_it, bool> index_ib;
- //-------------------------------
- scoped_lock<rmutex> guard(m_header);
- //-------------------------------
- //Insert the node. This can throw.
- //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.
- //
- //Since equal_range(key) + insert(hint, value) approach is
- //quite inefficient in container implementations
- //(they re-test if the position is correct), I've chosen
- //to insert the node, do an ugly un-const cast and modify
- //the key (which is a smart pointer) to an equivalent one
- index_ib insert_ret;
- BOOST_TRY{
- insert_ret = index.insert(value_type(key_type (name, namelen), mapped_type(0)));
- }
- //Ignore exceptions
- BOOST_CATCH(...){
- if(dothrow)
- BOOST_RETHROW;
- return 0;
- }
- BOOST_CATCH_END
- index_it it = insert_ret.first;
- //If found and this is find or construct, return data
- //else return null
- 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 0;
- }
- //Initialize the node value_eraser to erase inserted node
- //if something goes wrong
- value_eraser<index_type> v_eraser(index, it);
- //Allocates buffer for name + data, this can throw (it hurts)
- void *buffer_ptr;
- block_header_t * hdr;
- //Allocate and construct the headers
- if(is_node_index_t::value){
- size_type total_size = block_info.template total_size_with_header<index_it>();
- if(dothrow){
- buffer_ptr = this->allocate(total_size);
- }
- else{
- buffer_ptr = this->allocate(total_size, std::nothrow_t());
- if(!buffer_ptr)
- return 0;
- }
- index_it *idr = new(buffer_ptr) index_it(it);
- hdr = block_header_t::template from_first_header<index_it>(idr);
- }
- else{
- if(dothrow){
- buffer_ptr = this->allocate(block_info.total_size());
- }
- else{
- buffer_ptr = this->allocate(block_info.total_size(), std::nothrow_t());
- if(!buffer_ptr)
- return 0;
- }
- hdr = static_cast<block_header_t*>(buffer_ptr);
- }
- hdr = new(hdr)block_header_t(block_info);
- void *ptr = 0; //avoid gcc warning
- 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);
- //Do the ugly cast, please mama, forgive me!
- //This new key points to an identical string, so it must have the
- //same position than the overwritten key according to the predicate
- const_cast<key_type &>(it->first).name(name_ptr);
- it->second.m_ptr = hdr;
- //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));
- //Construct array, this can throw
- ipcdetail::array_construct(ptr, num, table);
- //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;
- }
- private:
- //!Returns the this pointer
- segment_manager *get_this_pointer()
- { return this; }
- typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex;
- scoped_lock<rmutex> priv_get_lock(bool use_lock)
- {
- scoped_lock<rmutex> local(m_header, defer_lock);
- if(use_lock){
- local.lock();
- }
- return scoped_lock<rmutex>(boost::move(local));
- }
- //!This struct includes needed data and derives from
- //!rmutex to allow EBO when using null interprocess_mutex
- struct header_t
- : public rmutex
- {
- named_index_t m_named_index;
- unique_index_t m_unique_index;
- header_t(Base *restricted_segment_mngr)
- : m_named_index (restricted_segment_mngr)
- , m_unique_index(restricted_segment_mngr)
- {}
- } m_header;
- /// @endcond
- };
- }} //namespace boost { namespace interprocess
- #include <boost/interprocess/detail/config_end.hpp>
- #endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
|