segment_manager.hpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/interprocess for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
  11. #define BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
  12. #ifndef BOOST_CONFIG_HPP
  13. # include <boost/config.hpp>
  14. #endif
  15. #
  16. #if defined(BOOST_HAS_PRAGMA_ONCE)
  17. # pragma once
  18. #endif
  19. #include <boost/interprocess/detail/config_begin.hpp>
  20. #include <boost/interprocess/detail/workaround.hpp>
  21. #include <boost/interprocess/detail/type_traits.hpp>
  22. #include <boost/interprocess/detail/transform_iterator.hpp>
  23. #include <boost/interprocess/detail/mpl.hpp>
  24. #include <boost/interprocess/detail/nothrow.hpp>
  25. #include <boost/interprocess/detail/segment_manager_helper.hpp>
  26. #include <boost/interprocess/detail/named_proxy.hpp>
  27. #include <boost/interprocess/detail/utilities.hpp>
  28. #include <boost/interprocess/offset_ptr.hpp>
  29. #include <boost/interprocess/indexes/iset_index.hpp>
  30. #include <boost/interprocess/exceptions.hpp>
  31. #include <boost/interprocess/allocators/allocator.hpp>
  32. #include <boost/interprocess/smart_ptr/deleter.hpp>
  33. #include <boost/move/utility_core.hpp>
  34. #include <boost/interprocess/sync/scoped_lock.hpp>
  35. // container/detail
  36. #include <boost/container/detail/minimal_char_traits_header.hpp>
  37. #include <boost/container/detail/placement_new.hpp>
  38. // std
  39. #include <cstddef> //std::size_t
  40. #include <boost/intrusive/detail/minimal_pair_header.hpp>
  41. #include <boost/assert.hpp>
  42. #ifndef BOOST_NO_EXCEPTIONS
  43. #include <exception>
  44. #endif
  45. #include <typeinfo>
  46. //!\file
  47. //!Describes the object placed in a memory segment that provides
  48. //!named object allocation capabilities for single-segment and
  49. //!multi-segment allocations.
  50. namespace boost{
  51. namespace interprocess{
  52. //!This object is the public base class of segment manager.
  53. //!This class only depends on the memory allocation algorithm
  54. //!and implements all the allocation features not related
  55. //!to named or unique objects.
  56. //!
  57. //!Storing a reference to segment_manager forces
  58. //!the holder class to be dependent on index types and character types.
  59. //!When such dependence is not desirable and only anonymous and raw
  60. //!allocations are needed, segment_manager_base is the correct answer.
  61. template<class MemoryAlgorithm>
  62. class segment_manager_base
  63. : private MemoryAlgorithm
  64. {
  65. public:
  66. typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
  67. typedef typename MemoryAlgorithm::void_pointer void_pointer;
  68. typedef typename MemoryAlgorithm::mutex_family mutex_family;
  69. static const std::size_t MemAlignment = MemoryAlgorithm::Alignment;
  70. typedef MemoryAlgorithm memory_algorithm;
  71. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  72. //Experimental. Don't use
  73. typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain;
  74. typedef typename MemoryAlgorithm::difference_type difference_type;
  75. typedef typename MemoryAlgorithm::size_type size_type;
  76. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  77. //!This constant indicates the payload size
  78. //!associated with each allocation of the memory algorithm
  79. static const size_type PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation;
  80. //!Constructor of the segment_manager_base
  81. //!
  82. //!"size" is the size of the memory segment where
  83. //!the basic segment manager is being constructed.
  84. //!
  85. //!"reserved_bytes" is the number of bytes
  86. //!after the end of the memory algorithm object itself
  87. //!that the memory algorithm will exclude from
  88. //!dynamic allocation
  89. //!
  90. //!Can throw
  91. segment_manager_base(size_type sz, size_type reserved_bytes)
  92. : MemoryAlgorithm(sz, reserved_bytes)
  93. {
  94. BOOST_ASSERT((sizeof(segment_manager_base<MemoryAlgorithm>) == sizeof(MemoryAlgorithm)));
  95. }
  96. //!Returns the size of the memory
  97. //!segment
  98. size_type get_size() const
  99. { return MemoryAlgorithm::get_size(); }
  100. //!Returns the number of free bytes of the memory
  101. //!segment
  102. size_type get_free_memory() const
  103. { return MemoryAlgorithm::get_free_memory(); }
  104. //!Obtains the minimum size needed by
  105. //!the segment manager
  106. static size_type get_min_size (size_type size)
  107. { return MemoryAlgorithm::get_min_size(size); }
  108. //!Allocates nbytes bytes. This function is only used in
  109. //!single-segment management. Never throws
  110. void * allocate (size_type nbytes, const std::nothrow_t &)
  111. { return MemoryAlgorithm::allocate(nbytes); }
  112. //!Returns a reference to the internal memory algorithm.
  113. //!This function is useful for custom memory algorithms that
  114. //!need additional configuration options after construction. Never throws.
  115. //!This function should be only used by advanced users.
  116. MemoryAlgorithm &get_memory_algorithm()
  117. { return static_cast<MemoryAlgorithm&>(*this); }
  118. //!Returns a const reference to the internal memory algorithm.
  119. //!This function is useful for custom memory algorithms that
  120. //!need additional configuration options after construction. Never throws.
  121. //!This function should be only used by advanced users.
  122. const MemoryAlgorithm &get_memory_algorithm() const
  123. { return static_cast<const MemoryAlgorithm&>(*this); }
  124. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  125. //Experimental. Dont' use.
  126. //!Allocates n_elements of elem_bytes bytes.
  127. //!Throws bad_alloc on failure. chain.size() is not increased on failure.
  128. void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
  129. {
  130. size_type prev_size = chain.size();
  131. MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain);
  132. if(!elem_bytes || chain.size() == prev_size){
  133. throw bad_alloc();
  134. }
  135. }
  136. //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
  137. //!Throws bad_alloc on failure. chain.size() is not increased on failure.
  138. void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
  139. {
  140. size_type prev_size = chain.size();
  141. MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, chain);
  142. if(!sizeof_element || chain.size() == prev_size){
  143. throw bad_alloc();
  144. }
  145. }
  146. //!Allocates n_elements of elem_bytes bytes.
  147. //!Non-throwing version. chain.size() is not increased on failure.
  148. void allocate_many(const std::nothrow_t &, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
  149. { MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); }
  150. //!Allocates n_elements, each one of
  151. //!element_lengths[i]*sizeof_element bytes.
  152. //!Non-throwing version. chain.size() is not increased on failure.
  153. void allocate_many(const std::nothrow_t &, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
  154. { MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, chain); }
  155. //!Deallocates all elements contained in chain.
  156. //!Never throws.
  157. void deallocate_many(multiallocation_chain &chain)
  158. { MemoryAlgorithm::deallocate_many(chain); }
  159. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  160. //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc
  161. //!on failure
  162. void * allocate(size_type nbytes)
  163. {
  164. void * ret = MemoryAlgorithm::allocate(nbytes);
  165. if(!ret)
  166. throw bad_alloc();
  167. return ret;
  168. }
  169. //!Allocates nbytes bytes. This function is only used in
  170. //!single-segment management. Never throws
  171. void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &)
  172. { return MemoryAlgorithm::allocate_aligned(nbytes, alignment); }
  173. //!Allocates nbytes bytes. This function is only used in
  174. //!single-segment management. Throws bad_alloc when fails
  175. void * allocate_aligned(size_type nbytes, size_type alignment)
  176. {
  177. void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
  178. if(!ret)
  179. throw bad_alloc();
  180. return ret;
  181. }
  182. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  183. template<class T>
  184. T *allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
  185. size_type &prefer_in_recvd_out_size, T *&reuse)
  186. {
  187. T *ret = MemoryAlgorithm::allocation_command
  188. (command | boost::interprocess::nothrow_allocation, limit_size, prefer_in_recvd_out_size, reuse);
  189. if(!(command & boost::interprocess::nothrow_allocation) && !ret)
  190. throw bad_alloc();
  191. return ret;
  192. }
  193. void *raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects,
  194. size_type &prefer_in_recvd_out_size, void *&reuse, size_type sizeof_object = 1)
  195. {
  196. void *ret = MemoryAlgorithm::raw_allocation_command
  197. ( command | boost::interprocess::nothrow_allocation, limit_objects,
  198. prefer_in_recvd_out_size, reuse, sizeof_object);
  199. if(!(command & boost::interprocess::nothrow_allocation) && !ret)
  200. throw bad_alloc();
  201. return ret;
  202. }
  203. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  204. //!Deallocates the bytes allocated with allocate/allocate_many()
  205. //!pointed by addr
  206. void deallocate (void *addr)
  207. { MemoryAlgorithm::deallocate(addr); }
  208. //!Increases managed memory in extra_size bytes more. This only works
  209. //!with single-segment management.
  210. void grow(size_type extra_size)
  211. {
  212. //Growing managed segments that use raw pointers is UB, so disallow it.
  213. BOOST_INTERPROCESS_STATIC_ASSERT(!(ipcdetail::is_same<void*, void_pointer>::value));
  214. MemoryAlgorithm::grow(extra_size);
  215. }
  216. //!Decreases managed memory to the minimum. This only works
  217. //!with single-segment management.
  218. void shrink_to_fit()
  219. { MemoryAlgorithm::shrink_to_fit(); }
  220. //!Returns the result of "all_memory_deallocated()" function
  221. //!of the used memory algorithm
  222. bool all_memory_deallocated()
  223. { return MemoryAlgorithm::all_memory_deallocated(); }
  224. //!Returns the result of "check_sanity()" function
  225. //!of the used memory algorithm
  226. bool check_sanity()
  227. { return MemoryAlgorithm::check_sanity(); }
  228. //!Writes to zero free memory (memory not yet allocated)
  229. //!of the memory algorithm
  230. void zero_free_memory()
  231. { MemoryAlgorithm::zero_free_memory(); }
  232. //!Returns the size of the buffer previously allocated pointed by ptr
  233. size_type size(const void *ptr) const
  234. { return MemoryAlgorithm::size(ptr); }
  235. };
  236. //!This object is placed in the beginning of memory segment and
  237. //!implements the allocation (named or anonymous) of portions
  238. //!of the segment. This object contains two indexes that
  239. //!maintain an association between a name and a portion of the segment.
  240. //!
  241. //!The first index contains the mappings for normal named objects using the
  242. //!char type specified in the template parameter.
  243. //!
  244. //!The second index contains the association for unique instances. The key will
  245. //!be the const char * returned from type_info.name() function for the unique
  246. //!type to be constructed.
  247. //!
  248. //!segment_manager<CharType, MemoryAlgorithm, IndexType> inherits publicly
  249. //!from segment_manager_base<MemoryAlgorithm> and inherits from it
  250. //!many public functions related to anonymous object and raw memory allocation.
  251. //!See segment_manager_base reference to know about those functions.
  252. template<class CharType
  253. ,class MemoryAlgorithm
  254. ,template<class IndexConfig> class IndexType>
  255. class segment_manager
  256. : public segment_manager_base<MemoryAlgorithm>
  257. {
  258. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  259. //Non-copyable
  260. segment_manager();
  261. segment_manager(const segment_manager &);
  262. segment_manager &operator=(const segment_manager &);
  263. typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_t;
  264. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  265. public:
  266. typedef MemoryAlgorithm memory_algorithm;
  267. typedef typename segment_manager_base_t::void_pointer void_pointer;
  268. typedef typename segment_manager_base_t::size_type size_type;
  269. typedef typename segment_manager_base_t::difference_type difference_type;
  270. typedef CharType char_type;
  271. typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
  272. static const size_type PayloadPerAllocation = segment_manager_base_t::PayloadPerAllocation;
  273. static const size_type MemAlignment = segment_manager_base_t::MemAlignment;
  274. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  275. private:
  276. typedef ipcdetail::block_header<size_type> block_header_t;
  277. typedef ipcdetail::index_config<CharType, MemoryAlgorithm> index_config_named;
  278. typedef ipcdetail::index_config<char, MemoryAlgorithm> index_config_unique;
  279. typedef IndexType<index_config_named> index_type;
  280. typedef ipcdetail::bool_<is_intrusive_index<index_type>::value > is_intrusive_t;
  281. typedef ipcdetail::bool_<is_node_index<index_type>::value> is_node_index_t;
  282. public:
  283. typedef IndexType<index_config_named> named_index_t;
  284. typedef IndexType<index_config_unique> unique_index_t;
  285. typedef ipcdetail::char_ptr_holder<CharType> char_ptr_holder_t;
  286. typedef ipcdetail::segment_manager_iterator_transform
  287. <typename named_index_t::const_iterator
  288. ,is_intrusive_index<index_type>::value> named_transform;
  289. typedef ipcdetail::segment_manager_iterator_transform
  290. <typename unique_index_t::const_iterator
  291. ,is_intrusive_index<index_type>::value> unique_transform;
  292. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  293. typedef typename segment_manager_base_t::mutex_family mutex_family;
  294. typedef transform_iterator
  295. <typename named_index_t::const_iterator, named_transform> const_named_iterator;
  296. typedef transform_iterator
  297. <typename unique_index_t::const_iterator, unique_transform> const_unique_iterator;
  298. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  299. //!Constructor proxy object definition helper class
  300. template<class T>
  301. struct construct_proxy
  302. {
  303. typedef ipcdetail::named_proxy<segment_manager, T, false> type;
  304. };
  305. //!Constructor proxy object definition helper class
  306. template<class T>
  307. struct construct_iter_proxy
  308. {
  309. typedef ipcdetail::named_proxy<segment_manager, T, true> type;
  310. };
  311. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  312. //!Constructor of the segment manager
  313. //!"size" is the size of the memory segment where
  314. //!the segment manager is being constructed.
  315. //!Can throw
  316. explicit segment_manager(size_type segment_size)
  317. : segment_manager_base_t(segment_size, priv_get_reserved_bytes())
  318. , m_header(static_cast<segment_manager_base_t*>(get_this_pointer()))
  319. {
  320. (void) anonymous_instance; (void) unique_instance;
  321. //Check EBO is applied, it's required
  322. const void * const this_addr = this;
  323. const void *const segm_addr = static_cast<segment_manager_base_t*>(this);
  324. (void)this_addr; (void)segm_addr;
  325. BOOST_ASSERT( this_addr == segm_addr);
  326. const std::size_t void_ptr_alignment = boost::move_detail::alignment_of<void_pointer>::value; (void)void_ptr_alignment;
  327. BOOST_ASSERT((0 == (std::size_t)this_addr % boost::move_detail::alignment_of<segment_manager>::value));
  328. }
  329. //!Tries to find a previous named/unique allocation. Returns the address
  330. //!and the object count. On failure the first member of the
  331. //!returned pair is 0.
  332. template <class T>
  333. std::pair<T*, size_type> find (char_ptr_holder_t name)
  334. { return this->priv_find_impl<T>(name, true); }
  335. //!Tries to find a previous named/unique allocation. Returns the address
  336. //!and the object count. On failure the first member of the
  337. //!returned pair is 0. This search is not mutex-protected!
  338. //!Use it only inside atomic_func() calls, where the internal mutex
  339. //!is guaranteed to be locked.
  340. template <class T>
  341. std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name)
  342. { return this->priv_find_impl<T>(name, false); }
  343. //!Returns throwing "construct" proxy
  344. //!object
  345. template <class T>
  346. typename construct_proxy<T>::type
  347. construct(char_ptr_holder_t name)
  348. { return typename construct_proxy<T>::type (this, name, false, true); }
  349. //!Returns throwing "search or construct" proxy
  350. //!object
  351. template <class T>
  352. typename construct_proxy<T>::type find_or_construct(char_ptr_holder_t name)
  353. { return typename construct_proxy<T>::type (this, name, true, true); }
  354. //!Returns no throwing "construct" proxy
  355. //!object
  356. template <class T>
  357. typename construct_proxy<T>::type
  358. construct(char_ptr_holder_t name, const std::nothrow_t &)
  359. { return typename construct_proxy<T>::type (this, name, false, false); }
  360. //!Returns no throwing "search or construct"
  361. //!proxy object
  362. template <class T>
  363. typename construct_proxy<T>::type
  364. find_or_construct(char_ptr_holder_t name, const std::nothrow_t &)
  365. { return typename construct_proxy<T>::type (this, name, true, false); }
  366. //!Returns throwing "construct from iterators" proxy object
  367. template <class T>
  368. typename construct_iter_proxy<T>::type
  369. construct_it(char_ptr_holder_t name)
  370. { return typename construct_iter_proxy<T>::type (this, name, false, true); }
  371. //!Returns throwing "search or construct from iterators"
  372. //!proxy object
  373. template <class T>
  374. typename construct_iter_proxy<T>::type
  375. find_or_construct_it(char_ptr_holder_t name)
  376. { return typename construct_iter_proxy<T>::type (this, name, true, true); }
  377. //!Returns no throwing "construct from iterators"
  378. //!proxy object
  379. template <class T>
  380. typename construct_iter_proxy<T>::type
  381. construct_it(char_ptr_holder_t name, const std::nothrow_t &)
  382. { return typename construct_iter_proxy<T>::type (this, name, false, false); }
  383. //!Returns no throwing "search or construct from iterators"
  384. //!proxy object
  385. template <class T>
  386. typename construct_iter_proxy<T>::type
  387. find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &)
  388. { return typename construct_iter_proxy<T>::type (this, name, true, false); }
  389. //!Calls object function blocking recursive interprocess_mutex and guarantees that
  390. //!no new named_alloc or destroy will be executed by any process while
  391. //!executing the object function call
  392. template <class Func>
  393. void atomic_func(Func &f)
  394. { scoped_lock<rmutex> guard(m_header); f(); }
  395. //!Tries to calls a functor guaranteeing that no new construction, search or
  396. //!destruction will be executed by any process while executing the object
  397. //!function call. If the atomic function can't be immediatelly executed
  398. //!because the internal mutex is already locked, returns false.
  399. //!If the functor throws, this function throws.
  400. template <class Func>
  401. bool try_atomic_func(Func &f)
  402. {
  403. scoped_lock<rmutex> guard(m_header, try_to_lock);
  404. if(guard){
  405. f();
  406. return true;
  407. }
  408. else{
  409. return false;
  410. }
  411. }
  412. //!Destroys a previously created named/unique instance.
  413. //!Returns false if the object was not present.
  414. template <class T>
  415. bool destroy(char_ptr_holder_t name)
  416. {
  417. BOOST_ASSERT(!name.is_anonymous());
  418. if(name.is_unique()){
  419. return this->priv_generic_named_destroy<T, char>(typeid(T).name(), m_header.m_unique_index);
  420. }
  421. else{
  422. return this->priv_generic_named_destroy<T, CharType>(name.get(), m_header.m_named_index);
  423. }
  424. }
  425. //!Destroys an anonymous, unique or named object
  426. //!using its address
  427. template <class T>
  428. void destroy_ptr(const T *p)
  429. {
  430. priv_destroy_ptr(p);
  431. }
  432. //!Returns the name of an object created with construct/find_or_construct
  433. //!functions. Does not throw
  434. template<class T>
  435. static const CharType *get_instance_name(const T *ptr)
  436. { return priv_get_instance_name(block_header_t::block_header_from_value(ptr)); }
  437. //!Returns the length of an object created with construct/find_or_construct
  438. //!functions. Does not throw.
  439. template<class T>
  440. static size_type get_instance_length(const T *ptr)
  441. { return priv_get_instance_length(block_header_t::block_header_from_value(ptr), sizeof(T)); }
  442. //!Returns is the the name of an object created with construct/find_or_construct
  443. //!functions. Does not throw
  444. template<class T>
  445. static instance_type get_instance_type(const T *ptr)
  446. { return priv_get_instance_type(block_header_t::block_header_from_value(ptr)); }
  447. //!Preallocates needed index resources to optimize the
  448. //!creation of "num" named objects in the managed memory segment.
  449. //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
  450. void reserve_named_objects(size_type num)
  451. {
  452. //-------------------------------
  453. scoped_lock<rmutex> guard(m_header);
  454. //-------------------------------
  455. m_header.m_named_index.reserve(num);
  456. }
  457. //!Preallocates needed index resources to optimize the
  458. //!creation of "num" unique objects in the managed memory segment.
  459. //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
  460. void reserve_unique_objects(size_type num)
  461. {
  462. //-------------------------------
  463. scoped_lock<rmutex> guard(m_header);
  464. //-------------------------------
  465. m_header.m_unique_index.reserve(num);
  466. }
  467. //!Calls shrink_to_fit in both named and unique object indexes
  468. //!to try to free unused memory from those indexes.
  469. void shrink_to_fit_indexes()
  470. {
  471. //-------------------------------
  472. scoped_lock<rmutex> guard(m_header);
  473. //-------------------------------
  474. m_header.m_named_index.shrink_to_fit();
  475. m_header.m_unique_index.shrink_to_fit();
  476. }
  477. //!Returns the number of named objects stored in
  478. //!the segment.
  479. size_type get_num_named_objects()
  480. {
  481. //-------------------------------
  482. scoped_lock<rmutex> guard(m_header);
  483. //-------------------------------
  484. return m_header.m_named_index.size();
  485. }
  486. //!Returns the number of unique objects stored in
  487. //!the segment.
  488. size_type get_num_unique_objects()
  489. {
  490. //-------------------------------
  491. scoped_lock<rmutex> guard(m_header);
  492. //-------------------------------
  493. return m_header.m_unique_index.size();
  494. }
  495. //!Obtains the minimum size needed by the
  496. //!segment manager
  497. static size_type get_min_size()
  498. { return segment_manager_base_t::get_min_size(priv_get_reserved_bytes()); }
  499. //!Returns a constant iterator to the beginning of the information about
  500. //!the named allocations performed in this segment manager
  501. const_named_iterator named_begin() const
  502. {
  503. return (make_transform_iterator)
  504. (m_header.m_named_index.begin(), named_transform());
  505. }
  506. //!Returns a constant iterator to the end of the information about
  507. //!the named allocations performed in this segment manager
  508. const_named_iterator named_end() const
  509. {
  510. return (make_transform_iterator)
  511. (m_header.m_named_index.end(), named_transform());
  512. }
  513. //!Returns a constant iterator to the beginning of the information about
  514. //!the unique allocations performed in this segment manager
  515. const_unique_iterator unique_begin() const
  516. {
  517. return (make_transform_iterator)
  518. (m_header.m_unique_index.begin(), unique_transform());
  519. }
  520. //!Returns a constant iterator to the end of the information about
  521. //!the unique allocations performed in this segment manager
  522. const_unique_iterator unique_end() const
  523. {
  524. return (make_transform_iterator)
  525. (m_header.m_unique_index.end(), unique_transform());
  526. }
  527. //!This is the default allocator to allocate types T
  528. //!from this managed segment
  529. template<class T>
  530. struct allocator
  531. {
  532. typedef boost::interprocess::allocator<T, segment_manager> type;
  533. };
  534. //!Returns an instance of the default allocator for type T
  535. //!initialized that allocates memory from this segment manager.
  536. template<class T>
  537. typename allocator<T>::type
  538. get_allocator()
  539. { return typename allocator<T>::type(this); }
  540. //!This is the default deleter to delete types T
  541. //!from this managed segment.
  542. template<class T>
  543. struct deleter
  544. {
  545. typedef boost::interprocess::deleter<T, segment_manager> type;
  546. };
  547. //!Returns an instance of the default deleter for type T
  548. //!that will delete an object constructed in this segment manager.
  549. template<class T>
  550. typename deleter<T>::type
  551. get_deleter()
  552. { return typename deleter<T>::type(this); }
  553. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  554. //!Generic named/anonymous new function. Offers all the possibilities,
  555. //!such as throwing, search before creating, and the constructor is
  556. //!encapsulated in an object function.
  557. template<class Proxy>
  558. typename Proxy::object_type * generic_construct
  559. (Proxy& pr, const CharType *name, size_type num, bool try2find, bool dothrow)
  560. {
  561. typedef typename Proxy::object_type object_type;
  562. //Security overflow check
  563. if(num > ((size_type)-1)/sizeof(object_type)){
  564. return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
  565. }
  566. if(name == 0){
  567. return this->priv_anonymous_construct(pr, num, dothrow);
  568. }
  569. else if(name == reinterpret_cast<const CharType*>(-1)){
  570. return this->priv_generic_named_construct
  571. (pr, unique_type, typeid(object_type).name(), num, try2find, dothrow, m_header.m_unique_index);
  572. }
  573. else{
  574. return this->priv_generic_named_construct
  575. (pr, named_type, name, num, try2find, dothrow, m_header.m_named_index);
  576. }
  577. }
  578. private:
  579. //!Tries to find a previous named allocation. Returns the address
  580. //!and the object count. On failure the first member of the
  581. //!returned pair is 0.
  582. template <class T>
  583. std::pair<T*, size_type> priv_find_impl (const CharType* name, bool lock)
  584. {
  585. //The name can't be null, no anonymous object can be found by name
  586. BOOST_ASSERT(name != 0);
  587. size_type sz;
  588. void *ret;
  589. if(name == reinterpret_cast<const CharType*>(-1)){
  590. ret = priv_generic_find<T>(typeid(T).name(), m_header.m_unique_index, sz, lock);
  591. }
  592. else{
  593. ret = priv_generic_find<T>(name, m_header.m_named_index, sz, lock);
  594. }
  595. return std::pair<T*, size_type>(static_cast<T*>(ret), sz);
  596. }
  597. //!Tries to find a previous unique allocation. Returns the address
  598. //!and the object count. On failure the first member of the
  599. //!returned pair is 0.
  600. template <class T>
  601. std::pair<T*, size_type> priv_find_impl (const ipcdetail::unique_instance_t*, bool lock)
  602. {
  603. size_type size;
  604. void *ret = priv_generic_find<T>(typeid(T).name(), m_header.m_unique_index, size, lock);
  605. return std::pair<T*, size_type>(static_cast<T*>(ret), size);
  606. }
  607. template<class Proxy>
  608. typename Proxy::object_type * priv_anonymous_construct(Proxy pr, size_type num, bool dothrow)
  609. {
  610. typedef typename Proxy::object_type object_type;
  611. BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment = boost::move_detail::alignment_of<object_type>::value;
  612. block_header_t block_info ( size_type(sizeof(object_type)*num)
  613. , size_type(t_alignment)
  614. , anonymous_type
  615. , 1
  616. , 0);
  617. //Check if there is enough memory
  618. const std::size_t total_size = block_info.template total_anonymous_size<t_alignment>();
  619. #if (BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI < 2)
  620. void *ptr_struct = this->allocate(total_size, nothrow<>::get());
  621. #else
  622. void* ptr_struct = this->allocate_aligned(total_size, t_alignment, nothrow<>::get());
  623. #endif
  624. if(!ptr_struct){
  625. return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
  626. }
  627. //Build scoped ptr to avoid leaks with constructor exception
  628. ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
  629. (ptr_struct, *static_cast<segment_manager_base_type*>(this));
  630. //Now construct the header
  631. const std::size_t front_space = block_header_t::template front_space_without_header<t_alignment>();
  632. block_header_t * const hdr = ::new((char*)ptr_struct + front_space, boost_container_new_t()) block_header_t(block_info);
  633. BOOST_ASSERT(is_ptr_aligned(hdr));
  634. void *ptr = 0; //avoid gcc warning
  635. ptr = hdr->value();
  636. //Now call constructors
  637. pr.construct_n(ptr, num);
  638. //All constructors successful, disable rollback
  639. mem.release();
  640. object_type* const pret = static_cast<object_type*>(ptr);
  641. BOOST_ASSERT(is_ptr_aligned(pret));
  642. return pret;
  643. }
  644. //!Calls the destructor and makes an anonymous deallocate
  645. template <class T>
  646. void priv_anonymous_destroy(const T *object)
  647. {
  648. BOOST_ASSERT(is_ptr_aligned(object));
  649. //Get control data from associated with this object
  650. block_header_t *ctrl_data = block_header_t::block_header_from_value(object);
  651. //-------------------------------
  652. //scoped_lock<rmutex> guard(m_header);
  653. //-------------------------------
  654. //This is not an anonymous object, the pointer is wrong!
  655. BOOST_ASSERT(ctrl_data->alloc_type() == anonymous_type);
  656. //Call destructors and free memory
  657. //Build scoped ptr to avoid leaks with destructor exception
  658. priv_destroy_n(object, ctrl_data->value_bytes()/sizeof(T));
  659. BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment =
  660. boost::move_detail::alignment_of<T>::value;
  661. const std::size_t front_space = block_header_t::template front_space_without_header<t_alignment>();
  662. this->deallocate((char*)ctrl_data - front_space);
  663. }
  664. template<class T>
  665. void priv_destroy_ptr(const T *ptr)
  666. {
  667. BOOST_ASSERT(is_ptr_aligned(ptr));
  668. block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr);
  669. switch(ctrl_data->alloc_type()){
  670. case anonymous_type:
  671. this->priv_anonymous_destroy(ptr);
  672. break;
  673. case named_type:
  674. this->priv_generic_named_destroy<T, CharType>
  675. (ctrl_data, m_header.m_named_index, is_node_index_t());
  676. break;
  677. case unique_type:
  678. this->priv_generic_named_destroy<T, char>
  679. (ctrl_data, m_header.m_unique_index, is_node_index_t());
  680. break;
  681. default:
  682. //This type is unknown, bad pointer passed to this function!
  683. BOOST_ASSERT(0);
  684. break;
  685. }
  686. }
  687. template<class T>
  688. static void priv_destroy_n(T* memory, std::size_t num)
  689. {
  690. for (std::size_t destroyed = 0; destroyed < num; ++destroyed)
  691. (memory++)->~T();
  692. }
  693. //!Returns the name of an object created with construct/find_or_construct
  694. //!functions. Does not throw
  695. static const CharType *priv_get_instance_name(block_header_t *ctrl_data)
  696. {
  697. boost::interprocess::allocation_type type = ctrl_data->alloc_type();
  698. if(type == anonymous_type){
  699. BOOST_ASSERT(ctrl_data->name_length() == 0);
  700. return 0;
  701. }
  702. BOOST_ASSERT(ctrl_data->name_length() != 0);
  703. CharType *name = static_cast<CharType*>(ctrl_data->template name<CharType>());
  704. //Sanity checks
  705. BOOST_ASSERT(ctrl_data->name_length() == std::char_traits<CharType>::length(name));
  706. return name;
  707. }
  708. static size_type priv_get_instance_length(block_header_t *ctrl_data, size_type sizeofvalue)
  709. {
  710. //Get header
  711. BOOST_ASSERT((ctrl_data->value_bytes() %sizeofvalue) == 0);
  712. return ctrl_data->value_bytes()/sizeofvalue;
  713. }
  714. //!Returns is the the name of an object created with construct/find_or_construct
  715. //!functions. Does not throw
  716. static instance_type priv_get_instance_type(block_header_t *ctrl_data)
  717. {
  718. //Get header
  719. BOOST_ASSERT((instance_type)ctrl_data->alloc_type() < max_allocation_type);
  720. return (instance_type)ctrl_data->alloc_type();
  721. }
  722. static size_type priv_get_reserved_bytes()
  723. {
  724. //Get the number of bytes until the end of (*this)
  725. //beginning in the end of the segment_manager_base_t base.
  726. return sizeof(segment_manager) - sizeof(segment_manager_base_t);
  727. }
  728. template <class T, class CharT>
  729. T *priv_generic_find
  730. (const CharT* name,
  731. IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
  732. size_type &length, bool use_lock)
  733. {
  734. typedef IndexType<ipcdetail::index_config
  735. <CharT, MemoryAlgorithm> > index_t;
  736. typedef typename index_t::iterator index_it;
  737. typedef typename index_t::compare_key_type compare_key_t;
  738. //-------------------------------
  739. scoped_lock<rmutex> guard(priv_get_lock(use_lock));
  740. //-------------------------------
  741. //Find name in index
  742. compare_key_t key (name, std::char_traits<CharT>::length(name));
  743. index_it it = index.find(key);
  744. //Initialize return values
  745. void *ret_ptr = 0;
  746. length = 0;
  747. //If found, assign values
  748. if(it != index.end()){
  749. //Get header
  750. block_header_t *ctrl_data = priv_block_header_from_it(it, is_intrusive_t());
  751. //Sanity check
  752. BOOST_ASSERT((ctrl_data->value_bytes() % sizeof(T)) == 0);
  753. ret_ptr = ctrl_data->value();
  754. length = ctrl_data->value_bytes()/ sizeof(T);
  755. }
  756. return static_cast<T*>(ret_ptr);
  757. }
  758. template <class T, class CharT>
  759. bool priv_generic_named_destroy
  760. (block_header_t *block_header
  761. ,IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index
  762. ,ipcdetail::true_ is_node_index)
  763. {
  764. (void)is_node_index;
  765. typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
  766. typedef typename index_t::index_data_t index_data_t;
  767. index_data_t* si = block_header_t::template to_first_header<index_data_t>(block_header);
  768. return this->priv_generic_named_destroy_impl<T, CharT>(*si, index);
  769. }
  770. template <class T, class CharT>
  771. bool priv_generic_named_destroy
  772. (block_header_t *block_header
  773. ,IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index
  774. ,ipcdetail::false_ is_node_index)
  775. {
  776. (void)is_node_index;
  777. CharT *name = static_cast<CharT*>(block_header->template name<CharT>());
  778. return this->priv_generic_named_destroy<T, CharT>(name, index);
  779. }
  780. template <class T, class CharT>
  781. bool priv_generic_named_destroy(const CharT *name,
  782. IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
  783. {
  784. typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
  785. typedef typename index_t::iterator index_it;
  786. typedef typename index_t::compare_key_type compare_key_t;
  787. //-------------------------------
  788. scoped_lock<rmutex> guard(m_header);
  789. //-------------------------------
  790. //Find name in index
  791. compare_key_t key(name, std::char_traits<CharT>::length(name));
  792. index_it it = index.find(key);
  793. //If not found, return false
  794. if(it == index.end()){
  795. //This name is not present in the index, wrong pointer or name!
  796. //BOOST_ASSERT(0);
  797. return false;
  798. }
  799. return this->priv_generic_named_destroy_impl<T, CharT>(it, index);
  800. }
  801. template <class T, class CharT>
  802. bool priv_generic_named_destroy_impl
  803. (typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator it,
  804. IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
  805. {
  806. typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
  807. typedef typename index_t::index_data_t index_data_t;
  808. //Get allocation parameters
  809. BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment =
  810. boost::move_detail::alignment_of<T>::value;
  811. block_header_t *ctrl_data = priv_block_header_from_it(it, is_intrusive_t());
  812. //Sanity checks
  813. BOOST_ASSERT((ctrl_data->value_bytes() % sizeof(T)) == 0);
  814. //Erase node from index
  815. index.erase(it);
  816. void *memory;
  817. BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value){
  818. index_data_t*ihdr = block_header_t::template to_first_header<index_data_t>(ctrl_data);
  819. const std::size_t front_space = block_header_t::template front_space_with_header<t_alignment, index_data_t>();
  820. memory = (char*)ihdr - front_space;
  821. ihdr->~index_data_t();
  822. }
  823. else{
  824. const std::size_t front_space = block_header_t::template front_space_without_header<t_alignment>();
  825. memory = (char*)ctrl_data - front_space;
  826. }
  827. //Call destructors and free memory
  828. priv_destroy_n(static_cast<T*>(ctrl_data->value()), ctrl_data->value_bytes()/sizeof(T));
  829. //Destroy the headers
  830. ctrl_data->~block_header_t();
  831. this->deallocate(memory);
  832. return true;
  833. }
  834. template<class IndexIt>
  835. static block_header_t* priv_block_header_from_it(IndexIt it, ipcdetail::true_) //is_intrusive
  836. { return block_header_t::from_first_header(&*it); }
  837. template<class IndexIt>
  838. static block_header_t* priv_block_header_from_it(IndexIt it, ipcdetail::false_ ) //!is_intrusive
  839. {
  840. return static_cast<block_header_t*>(ipcdetail::to_raw_pointer(it->second.m_ptr));
  841. }
  842. //!Generic named new function for
  843. //!named functions
  844. template<class Proxy, class CharT>
  845. typename Proxy::object_type * priv_generic_named_construct
  846. (Proxy pr, unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow,
  847. IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
  848. {
  849. typedef typename Proxy::object_type object_type;
  850. std::size_t namelen = std::char_traits<CharT>::length(name);
  851. BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment = boost::move_detail::alignment_of<object_type>::value;
  852. block_header_t block_info ( size_type(sizeof(object_type)*num)
  853. , size_type(t_alignment)
  854. , type
  855. , sizeof(CharT)
  856. , namelen);
  857. typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
  858. typedef typename index_t::iterator index_it;
  859. typedef typename index_t::compare_key_type compare_key_t;
  860. typedef typename index_t::insert_commit_data commit_data_t;
  861. typedef typename index_t::index_data_t index_data_t;
  862. //-------------------------------
  863. scoped_lock<rmutex> guard(m_header);
  864. //-------------------------------
  865. //First, we want to know if the key is already present before
  866. //we allocate any memory, and if the key is not present, we
  867. //want to allocate all memory in a single buffer that will
  868. //contain the name and the user buffer.
  869. index_it existing_it;
  870. bool found = false;
  871. commit_data_t commit_data;
  872. BOOST_INTERPROCESS_TRY{
  873. typedef std::pair<index_it, bool> index_ib;
  874. index_ib insert_ret = index.insert_check(compare_key_t(name, namelen), commit_data);
  875. existing_it = insert_ret.first;
  876. found = !insert_ret.second;
  877. }
  878. //Ignore exceptions
  879. BOOST_INTERPROCESS_CATCH(...){
  880. if(dothrow)
  881. BOOST_INTERPROCESS_RETHROW
  882. return 0;
  883. }
  884. BOOST_INTERPROCESS_CATCH_END
  885. //If found and this is find or construct, return data, error otherwise
  886. if(found){
  887. if(try2find){
  888. return static_cast<object_type*>(priv_block_header_from_it(existing_it, is_intrusive_t())->value());
  889. }
  890. return ipcdetail::null_or_already_exists<object_type>(dothrow);
  891. }
  892. //Allocates buffer for name + data, this can throw (it hurts)
  893. void *buffer_ptr;
  894. block_header_t * hdr;
  895. std::size_t front_space;
  896. //Allocate and construct the headers
  897. BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value){
  898. const size_type total_size = block_info.template total_named_size_with_header<t_alignment, CharT, index_data_t>(namelen);
  899. #if (BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI < 2)
  900. buffer_ptr = this->allocate(total_size, nothrow<>::get());
  901. #else
  902. buffer_ptr = this->allocate_aligned(total_size, t_alignment, nothrow<>::get());
  903. #endif
  904. if(!buffer_ptr)
  905. return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
  906. front_space = block_header_t::template front_space_with_header<t_alignment, index_data_t>();
  907. hdr = block_header_t::from_first_header(reinterpret_cast<index_data_t*>((void*)((char*)buffer_ptr + front_space)));
  908. }
  909. else{
  910. const size_type total_size = block_info.template total_named_size<t_alignment, CharT>(namelen);
  911. #if (BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI < 2)
  912. buffer_ptr = this->allocate(total_size, nothrow<>::get());
  913. #else
  914. buffer_ptr = this->allocate_aligned(total_size, t_alignment, nothrow<>::get());
  915. #endif
  916. front_space = block_header_t::template front_space_without_header<t_alignment>();
  917. //Check if there is enough memory
  918. if (!buffer_ptr)
  919. return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
  920. hdr = reinterpret_cast<block_header_t*>((void*)((char*)buffer_ptr + front_space));
  921. }
  922. BOOST_ASSERT(is_ptr_aligned(hdr));
  923. hdr = ::new(hdr, boost_container_new_t()) block_header_t(block_info);
  924. //Build scoped ptr to avoid leaks with constructor exception
  925. ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
  926. (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
  927. void *ptr = hdr->value();
  928. //Copy name to memory segment and insert data
  929. hdr->store_name_length(static_cast<typename block_header_t::name_len_t>(namelen));
  930. CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
  931. std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
  932. index_it it;
  933. BOOST_INTERPROCESS_TRY{
  934. BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value) {
  935. index_data_t* index_data = ::new((char*)buffer_ptr + front_space, boost_container_new_t()) index_data_t();
  936. BOOST_ASSERT(is_ptr_aligned(index_data));
  937. it = index.insert_commit(compare_key_t(name_ptr, namelen), hdr, *index_data, commit_data);
  938. }
  939. else{
  940. index_data_t id;
  941. it = index.insert_commit(compare_key_t(name_ptr, namelen), hdr, id, commit_data);
  942. }
  943. }
  944. //Ignore exceptions
  945. BOOST_INTERPROCESS_CATCH(...){
  946. if(dothrow)
  947. BOOST_INTERPROCESS_RETHROW
  948. return 0;
  949. }
  950. BOOST_INTERPROCESS_CATCH_END
  951. //Initialize the node value_eraser to erase inserted node
  952. //if something goes wrong
  953. value_eraser<index_t> v_eraser(index, it);
  954. //Construct array, this can throw
  955. pr.construct_n(ptr, num);
  956. //Release rollbacks since construction was successful
  957. v_eraser.release();
  958. mem.release();
  959. object_type* const pret = static_cast<object_type*>(ptr);
  960. BOOST_ASSERT(is_ptr_aligned(pret));
  961. return pret;
  962. }
  963. private:
  964. //!Returns the this pointer
  965. segment_manager *get_this_pointer()
  966. { return this; }
  967. typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex;
  968. scoped_lock<rmutex> priv_get_lock(bool use_lock)
  969. {
  970. scoped_lock<rmutex> local(m_header, defer_lock);
  971. if(use_lock){
  972. local.lock();
  973. }
  974. return scoped_lock<rmutex>(boost::move(local));
  975. }
  976. //!This struct includes needed data and derives from
  977. //!rmutex to allow EBO when using null interprocess_mutex
  978. struct header_t
  979. : public rmutex
  980. {
  981. named_index_t m_named_index;
  982. unique_index_t m_unique_index;
  983. header_t(segment_manager_base_t *segment_mngr_base)
  984. : m_named_index (segment_mngr_base)
  985. , m_unique_index(segment_mngr_base)
  986. {}
  987. } m_header;
  988. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  989. };
  990. }} //namespace boost { namespace interprocess
  991. #include <boost/interprocess/detail/config_end.hpp>
  992. #endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP