PageRenderTime 64ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/interprocess/segment_manager.hpp

http://hadesmem.googlecode.com/
C++ Header | 1361 lines | 839 code | 187 blank | 335 comment | 71 complexity | 649a334305859d9fb288f5ccb0c8ba45 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0, Apache-2.0, LGPL-3.0
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2005-2009. 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. #if (defined _MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif
  15. #include <boost/interprocess/detail/config_begin.hpp>
  16. #include <boost/interprocess/detail/workaround.hpp>
  17. #include <boost/detail/no_exceptions_support.hpp>
  18. #include <boost/interprocess/detail/type_traits.hpp>
  19. #include <boost/interprocess/detail/transform_iterator.hpp>
  20. #include <boost/interprocess/detail/mpl.hpp>
  21. #include <boost/interprocess/detail/segment_manager_helper.hpp>
  22. #include <boost/interprocess/detail/named_proxy.hpp>
  23. #include <boost/interprocess/detail/utilities.hpp>
  24. #include <boost/interprocess/offset_ptr.hpp>
  25. #include <boost/interprocess/indexes/iset_index.hpp>
  26. #include <boost/interprocess/exceptions.hpp>
  27. #include <boost/interprocess/allocators/allocator.hpp>
  28. #include <boost/interprocess/smart_ptr/deleter.hpp>
  29. #include <boost/interprocess/detail/move.hpp>
  30. #include <boost/interprocess/sync/scoped_lock.hpp>
  31. #include <cstddef> //std::size_t
  32. #include <string> //char_traits
  33. #include <new> //std::nothrow
  34. #include <utility> //std::pair
  35. #include <boost/assert.hpp>
  36. #ifndef BOOST_NO_EXCEPTIONS
  37. #include <exception>
  38. #endif
  39. //!\file
  40. //!Describes the object placed in a memory segment that provides
  41. //!named object allocation capabilities for single-segment and
  42. //!multi-segment allocations.
  43. namespace boost{
  44. namespace interprocess{
  45. //!This object is the public base class of segment manager.
  46. //!This class only depends on the memory allocation algorithm
  47. //!and implements all the allocation features not related
  48. //!to named or unique objects.
  49. //!
  50. //!Storing a reference to segment_manager forces
  51. //!the holder class to be dependent on index types and character types.
  52. //!When such dependence is not desirable and only anonymous and raw
  53. //!allocations are needed, segment_manager_base is the correct answer.
  54. template<class MemoryAlgorithm>
  55. class segment_manager_base
  56. : private MemoryAlgorithm
  57. {
  58. public:
  59. typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
  60. typedef typename MemoryAlgorithm::void_pointer void_pointer;
  61. typedef typename MemoryAlgorithm::mutex_family mutex_family;
  62. typedef MemoryAlgorithm memory_algorithm;
  63. /// @cond
  64. //Experimental. Don't use
  65. typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain;
  66. /// @endcond
  67. //!This constant indicates the payload size
  68. //!associated with each allocation of the memory algorithm
  69. static const std::size_t PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation;
  70. //!Constructor of the segment_manager_base
  71. //!
  72. //!"size" is the size of the memory segment where
  73. //!the basic segment manager is being constructed.
  74. //!
  75. //!"reserved_bytes" is the number of bytes
  76. //!after the end of the memory algorithm object itself
  77. //!that the memory algorithm will exclude from
  78. //!dynamic allocation
  79. //!
  80. //!Can throw
  81. segment_manager_base(std::size_t size, std::size_t reserved_bytes)
  82. : MemoryAlgorithm(size, reserved_bytes)
  83. {
  84. BOOST_ASSERT((sizeof(segment_manager_base<MemoryAlgorithm>) == sizeof(MemoryAlgorithm)));
  85. }
  86. //!Returns the size of the memory
  87. //!segment
  88. std::size_t get_size() const
  89. { return MemoryAlgorithm::get_size(); }
  90. //!Returns the number of free bytes of the memory
  91. //!segment
  92. std::size_t get_free_memory() const
  93. { return MemoryAlgorithm::get_free_memory(); }
  94. //!Obtains the minimum size needed by
  95. //!the segment manager
  96. static std::size_t get_min_size (std::size_t size)
  97. { return MemoryAlgorithm::get_min_size(size); }
  98. //!Allocates nbytes bytes. This function is only used in
  99. //!single-segment management. Never throws
  100. void * allocate (std::size_t nbytes, std::nothrow_t)
  101. { return MemoryAlgorithm::allocate(nbytes); }
  102. /// @cond
  103. //Experimental. Dont' use.
  104. //!Allocates n_elements of
  105. //!elem_size bytes. Throws bad_alloc on failure.
  106. multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t num_elements)
  107. {
  108. multiallocation_chain mem(MemoryAlgorithm::allocate_many(elem_bytes, num_elements));
  109. if(mem.empty()) throw bad_alloc();
  110. return boost::interprocess::move(mem);
  111. }
  112. //!Allocates n_elements, each one of
  113. //!element_lenghts[i]*sizeof_element bytes. Throws bad_alloc on failure.
  114. multiallocation_chain allocate_many
  115. (const std::size_t *element_lenghts, std::size_t n_elements, std::size_t sizeof_element = 1)
  116. {
  117. multiallocation_chain mem(MemoryAlgorithm::allocate_many(element_lenghts, n_elements, sizeof_element));
  118. if(mem.empty()) throw bad_alloc();
  119. return boost::interprocess::move(mem);
  120. }
  121. //!Allocates n_elements of
  122. //!elem_size bytes. Returns a default constructed iterator on failure.
  123. multiallocation_chain allocate_many
  124. (std::size_t elem_bytes, std::size_t num_elements, std::nothrow_t)
  125. { return MemoryAlgorithm::allocate_many(elem_bytes, num_elements); }
  126. //!Allocates n_elements, each one of
  127. //!element_lenghts[i]*sizeof_element bytes.
  128. //!Returns a default constructed iterator on failure.
  129. multiallocation_chain allocate_many
  130. (const std::size_t *elem_sizes, std::size_t n_elements, std::size_t sizeof_element, std::nothrow_t)
  131. { return MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element); }
  132. //!Deallocates elements pointed by the
  133. //!multiallocation iterator range.
  134. void deallocate_many(multiallocation_chain chain)
  135. { MemoryAlgorithm::deallocate_many(boost::interprocess::move(chain)); }
  136. /// @endcond
  137. //!Allocates nbytes bytes. Throws boost::interprocess::bad_alloc
  138. //!on failure
  139. void * allocate(std::size_t nbytes)
  140. {
  141. void * ret = MemoryAlgorithm::allocate(nbytes);
  142. if(!ret)
  143. throw bad_alloc();
  144. return ret;
  145. }
  146. //!Allocates nbytes bytes. This function is only used in
  147. //!single-segment management. Never throws
  148. void * allocate_aligned (std::size_t nbytes, std::size_t alignment, std::nothrow_t)
  149. { return MemoryAlgorithm::allocate_aligned(nbytes, alignment); }
  150. //!Allocates nbytes bytes. This function is only used in
  151. //!single-segment management. Throws bad_alloc when fails
  152. void * allocate_aligned(std::size_t nbytes, std::size_t alignment)
  153. {
  154. void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
  155. if(!ret)
  156. throw bad_alloc();
  157. return ret;
  158. }
  159. template<class T>
  160. std::pair<T *, bool>
  161. allocation_command (boost::interprocess::allocation_type command, std::size_t limit_size,
  162. std::size_t preferred_size,std::size_t &received_size,
  163. T *reuse_ptr = 0)
  164. {
  165. std::pair<T *, bool> ret = MemoryAlgorithm::allocation_command
  166. ( command | boost::interprocess::nothrow_allocation, limit_size, preferred_size, received_size
  167. , reuse_ptr);
  168. if(!(command & boost::interprocess::nothrow_allocation) && !ret.first)
  169. throw bad_alloc();
  170. return ret;
  171. }
  172. std::pair<void *, bool>
  173. raw_allocation_command (boost::interprocess::allocation_type command, std::size_t limit_objects,
  174. std::size_t preferred_objects,std::size_t &received_objects,
  175. void *reuse_ptr = 0, std::size_t sizeof_object = 1)
  176. {
  177. std::pair<void *, bool> ret = MemoryAlgorithm::raw_allocation_command
  178. ( command | boost::interprocess::nothrow_allocation, limit_objects, preferred_objects, received_objects
  179. , reuse_ptr, sizeof_object);
  180. if(!(command & boost::interprocess::nothrow_allocation) && !ret.first)
  181. throw bad_alloc();
  182. return ret;
  183. }
  184. //!Deallocates the bytes allocated with allocate/allocate_many()
  185. //!pointed by addr
  186. void deallocate (void *addr)
  187. { MemoryAlgorithm::deallocate(addr); }
  188. //!Increases managed memory in extra_size bytes more. This only works
  189. //!with single-segment management.
  190. void grow(std::size_t extra_size)
  191. { MemoryAlgorithm::grow(extra_size); }
  192. //!Decreases managed memory to the minimum. This only works
  193. //!with single-segment management.
  194. void shrink_to_fit()
  195. { MemoryAlgorithm::shrink_to_fit(); }
  196. //!Returns the result of "all_memory_deallocated()" function
  197. //!of the used memory algorithm
  198. bool all_memory_deallocated()
  199. { return MemoryAlgorithm::all_memory_deallocated(); }
  200. //!Returns the result of "check_sanity()" function
  201. //!of the used memory algorithm
  202. bool check_sanity()
  203. { return MemoryAlgorithm::check_sanity(); }
  204. //!Writes to zero free memory (memory not yet allocated)
  205. //!of the memory algorithm
  206. void zero_free_memory()
  207. { MemoryAlgorithm::zero_free_memory(); }
  208. //!Returns the size of the buffer previously allocated pointed by ptr
  209. std::size_t size(const void *ptr) const
  210. { return MemoryAlgorithm::size(ptr); }
  211. /// @cond
  212. protected:
  213. void * prot_anonymous_construct
  214. (std::size_t num, bool dothrow, detail::in_place_interface &table)
  215. {
  216. typedef detail::block_header block_header_t;
  217. block_header_t block_info ( table.size*num
  218. , table.alignment
  219. , anonymous_type
  220. , 1
  221. , 0);
  222. //Allocate memory
  223. void *ptr_struct = this->allocate(block_info.total_size(), std::nothrow_t());
  224. //Check if there is enough memory
  225. if(!ptr_struct){
  226. if(dothrow){
  227. throw bad_alloc();
  228. }
  229. else{
  230. return 0;
  231. }
  232. }
  233. //Build scoped ptr to avoid leaks with constructor exception
  234. detail::mem_algo_deallocator<MemoryAlgorithm> mem(ptr_struct, *this);
  235. //Now construct the header
  236. block_header_t * hdr = new(ptr_struct) block_header_t(block_info);
  237. void *ptr = 0; //avoid gcc warning
  238. ptr = hdr->value();
  239. //Now call constructors
  240. detail::array_construct(ptr, num, table);
  241. //All constructors successful, we don't want erase memory
  242. mem.release();
  243. return ptr;
  244. }
  245. //!Calls the destructor and makes an anonymous deallocate
  246. void prot_anonymous_destroy(const void *object, detail::in_place_interface &table)
  247. {
  248. //Get control data from associated with this object
  249. typedef detail::block_header block_header_t;
  250. block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment);
  251. //-------------------------------
  252. //scoped_lock<rmutex> guard(m_header);
  253. //-------------------------------
  254. if(ctrl_data->alloc_type() != anonymous_type){
  255. //This is not an anonymous object, the pointer is wrong!
  256. BOOST_ASSERT(0);
  257. }
  258. //Call destructors and free memory
  259. //Build scoped ptr to avoid leaks with destructor exception
  260. std::size_t destroyed = 0;
  261. table.destroy_n(const_cast<void*>(object), ctrl_data->m_value_bytes/table.size, destroyed);
  262. this->deallocate(ctrl_data);
  263. }
  264. /// @endcond
  265. };
  266. //!This object is placed in the beginning of memory segment and
  267. //!implements the allocation (named or anonymous) of portions
  268. //!of the segment. This object contains two indexes that
  269. //!maintain an association between a name and a portion of the segment.
  270. //!
  271. //!The first index contains the mappings for normal named objects using the
  272. //!char type specified in the template parameter.
  273. //!
  274. //!The second index contains the association for unique instances. The key will
  275. //!be the const char * returned from type_info.name() function for the unique
  276. //!type to be constructed.
  277. //!
  278. //!segment_manager<CharType, MemoryAlgorithm, IndexType> inherits publicly
  279. //!from segment_manager_base<MemoryAlgorithm> and inherits from it
  280. //!many public functions related to anonymous object and raw memory allocation.
  281. //!See segment_manager_base reference to know about those functions.
  282. template<class CharType
  283. ,class MemoryAlgorithm
  284. ,template<class IndexConfig> class IndexType>
  285. class segment_manager
  286. : public segment_manager_base<MemoryAlgorithm>
  287. {
  288. /// @cond
  289. //Non-copyable
  290. segment_manager();
  291. segment_manager(const segment_manager &);
  292. segment_manager &operator=(const segment_manager &);
  293. typedef segment_manager_base<MemoryAlgorithm> Base;
  294. typedef detail::block_header block_header_t;
  295. /// @endcond
  296. public:
  297. typedef MemoryAlgorithm memory_algorithm;
  298. typedef typename Base::void_pointer void_pointer;
  299. typedef CharType char_type;
  300. typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
  301. static const std::size_t PayloadPerAllocation = Base::PayloadPerAllocation;
  302. /// @cond
  303. private:
  304. typedef detail::index_config<CharType, MemoryAlgorithm> index_config_named;
  305. typedef detail::index_config<char, MemoryAlgorithm> index_config_unique;
  306. typedef IndexType<index_config_named> index_type;
  307. typedef detail::bool_<is_intrusive_index<index_type>::value > is_intrusive_t;
  308. typedef detail::bool_<is_node_index<index_type>::value> is_node_index_t;
  309. public:
  310. typedef IndexType<index_config_named> named_index_t;
  311. typedef IndexType<index_config_unique> unique_index_t;
  312. typedef detail::char_ptr_holder<CharType> char_ptr_holder_t;
  313. typedef detail::segment_manager_iterator_transform
  314. <typename named_index_t::const_iterator
  315. ,is_intrusive_index<index_type>::value> named_transform;
  316. typedef detail::segment_manager_iterator_transform
  317. <typename unique_index_t::const_iterator
  318. ,is_intrusive_index<index_type>::value> unique_transform;
  319. /// @endcond
  320. typedef typename Base::mutex_family mutex_family;
  321. typedef transform_iterator
  322. <typename named_index_t::const_iterator, named_transform> const_named_iterator;
  323. typedef transform_iterator
  324. <typename unique_index_t::const_iterator, unique_transform> const_unique_iterator;
  325. /// @cond
  326. //!Constructor proxy object definition helper class
  327. template<class T>
  328. struct construct_proxy
  329. {
  330. typedef detail::named_proxy<segment_manager, T, false> type;
  331. };
  332. //!Constructor proxy object definition helper class
  333. template<class T>
  334. struct construct_iter_proxy
  335. {
  336. typedef detail::named_proxy<segment_manager, T, true> type;
  337. };
  338. /// @endcond
  339. //!Constructor of the segment manager
  340. //!"size" is the size of the memory segment where
  341. //!the segment manager is being constructed.
  342. //!Can throw
  343. segment_manager(std::size_t size)
  344. : Base(size, priv_get_reserved_bytes())
  345. , m_header(static_cast<Base*>(get_this_pointer()))
  346. {
  347. (void) anonymous_instance; (void) unique_instance;
  348. BOOST_ASSERT(static_cast<const void*>(this) == static_cast<const void*>(static_cast<Base*>(this)));
  349. }
  350. //!Tries to find a previous named allocation. Returns the address
  351. //!and the object count. On failure the first member of the
  352. //!returned pair is 0.
  353. template <class T>
  354. std::pair<T*, std::size_t> find (const CharType* name)
  355. { return this->priv_find_impl<T>(name, true); }
  356. //!Tries to find a previous unique allocation. Returns the address
  357. //!and the object count. On failure the first member of the
  358. //!returned pair is 0.
  359. template <class T>
  360. std::pair<T*, std::size_t> find (const detail::unique_instance_t* name)
  361. { return this->priv_find_impl<T>(name, true); }
  362. //!Tries to find a previous named allocation. Returns the address
  363. //!and the object count. On failure the first member of the
  364. //!returned pair is 0. This search is not mutex-protected!
  365. template <class T>
  366. std::pair<T*, std::size_t> find_no_lock (const CharType* name)
  367. { return this->priv_find_impl<T>(name, false); }
  368. //!Tries to find a previous unique allocation. Returns the address
  369. //!and the object count. On failure the first member of the
  370. //!returned pair is 0. This search is not mutex-protected!
  371. template <class T>
  372. std::pair<T*, std::size_t> find_no_lock (const detail::unique_instance_t* name)
  373. { return this->priv_find_impl<T>(name, false); }
  374. //!Returns throwing "construct" proxy
  375. //!object
  376. template <class T>
  377. typename construct_proxy<T>::type
  378. construct(char_ptr_holder_t name)
  379. { return typename construct_proxy<T>::type (this, name, false, true); }
  380. //!Returns throwing "search or construct" proxy
  381. //!object
  382. template <class T>
  383. typename construct_proxy<T>::type find_or_construct(char_ptr_holder_t name)
  384. { return typename construct_proxy<T>::type (this, name, true, true); }
  385. //!Returns no throwing "construct" proxy
  386. //!object
  387. template <class T>
  388. typename construct_proxy<T>::type
  389. construct(char_ptr_holder_t name, std::nothrow_t)
  390. { return typename construct_proxy<T>::type (this, name, false, false); }
  391. //!Returns no throwing "search or construct"
  392. //!proxy object
  393. template <class T>
  394. typename construct_proxy<T>::type
  395. find_or_construct(char_ptr_holder_t name, std::nothrow_t)
  396. { return typename construct_proxy<T>::type (this, name, true, false); }
  397. //!Returns throwing "construct from iterators" proxy object
  398. template <class T>
  399. typename construct_iter_proxy<T>::type
  400. construct_it(char_ptr_holder_t name)
  401. { return typename construct_iter_proxy<T>::type (this, name, false, true); }
  402. //!Returns throwing "search or construct from iterators"
  403. //!proxy object
  404. template <class T>
  405. typename construct_iter_proxy<T>::type
  406. find_or_construct_it(char_ptr_holder_t name)
  407. { return typename construct_iter_proxy<T>::type (this, name, true, true); }
  408. //!Returns no throwing "construct from iterators"
  409. //!proxy object
  410. template <class T>
  411. typename construct_iter_proxy<T>::type
  412. construct_it(char_ptr_holder_t name, std::nothrow_t)
  413. { return typename construct_iter_proxy<T>::type (this, name, false, false); }
  414. //!Returns no throwing "search or construct from iterators"
  415. //!proxy object
  416. template <class T>
  417. typename construct_iter_proxy<T>::type
  418. find_or_construct_it(char_ptr_holder_t name, std::nothrow_t)
  419. { return typename construct_iter_proxy<T>::type (this, name, true, false); }
  420. //!Calls object function blocking recursive interprocess_mutex and guarantees that
  421. //!no new named_alloc or destroy will be executed by any process while
  422. //!executing the object function call*/
  423. template <class Func>
  424. void atomic_func(Func &f)
  425. { scoped_lock<rmutex> guard(m_header); f(); }
  426. //!Tries to calls a functor guaranteeing that no new construction, search or
  427. //!destruction will be executed by any process while executing the object
  428. //!function call. If the atomic function can't be immediatelly executed
  429. //!because the internal mutex is already locked, returns false.
  430. //!If the functor throws, this function throws.
  431. template <class Func>
  432. bool try_atomic_func(Func &f)
  433. {
  434. scoped_lock<rmutex> guard(m_header, try_to_lock);
  435. if(guard){
  436. f();
  437. return true;
  438. }
  439. else{
  440. return false;
  441. }
  442. }
  443. //!Destroys a previously created unique instance.
  444. //!Returns false if the object was not present.
  445. template <class T>
  446. bool destroy(const detail::unique_instance_t *)
  447. {
  448. detail::placement_destroy<T> dtor;
  449. return this->priv_generic_named_destroy<char>
  450. (typeid(T).name(), m_header.m_unique_index, dtor, is_intrusive_t());
  451. }
  452. //!Destroys the named object with
  453. //!the given name. Returns false if that object can't be found.
  454. template <class T>
  455. bool destroy(const CharType *name)
  456. {
  457. detail::placement_destroy<T> dtor;
  458. return this->priv_generic_named_destroy<CharType>
  459. (name, m_header.m_named_index, dtor, is_intrusive_t());
  460. }
  461. //!Destroys an anonymous, unique or named object
  462. //!using it's address
  463. template <class T>
  464. void destroy_ptr(const T *p)
  465. {
  466. //If T is void transform it to char
  467. typedef typename detail::char_if_void<T>::type data_t;
  468. detail::placement_destroy<data_t> dtor;
  469. priv_destroy_ptr(p, dtor);
  470. }
  471. //!Returns the name of an object created with construct/find_or_construct
  472. //!functions. Does not throw
  473. template<class T>
  474. static const CharType *get_instance_name(const T *ptr)
  475. { return priv_get_instance_name(block_header_t::block_header_from_value(ptr)); }
  476. //!Returns the length of an object created with construct/find_or_construct
  477. //!functions. Does not throw.
  478. template<class T>
  479. static std::size_t get_instance_length(const T *ptr)
  480. { return priv_get_instance_length(block_header_t::block_header_from_value(ptr), sizeof(T)); }
  481. //!Returns is the the name of an object created with construct/find_or_construct
  482. //!functions. Does not throw
  483. template<class T>
  484. static instance_type get_instance_type(const T *ptr)
  485. { return priv_get_instance_type(block_header_t::block_header_from_value(ptr)); }
  486. //!Preallocates needed index resources to optimize the
  487. //!creation of "num" named objects in the managed memory segment.
  488. //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
  489. void reserve_named_objects(std::size_t num)
  490. {
  491. //-------------------------------
  492. scoped_lock<rmutex> guard(m_header);
  493. //-------------------------------
  494. m_header.m_named_index.reserve(num);
  495. }
  496. //!Preallocates needed index resources to optimize the
  497. //!creation of "num" unique objects in the managed memory segment.
  498. //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
  499. void reserve_unique_objects(std::size_t num)
  500. {
  501. //-------------------------------
  502. scoped_lock<rmutex> guard(m_header);
  503. //-------------------------------
  504. m_header.m_unique_index.reserve(num);
  505. }
  506. //!Calls shrink_to_fit in both named and unique object indexes
  507. //!to try to free unused memory from those indexes.
  508. void shrink_to_fit_indexes()
  509. {
  510. //-------------------------------
  511. scoped_lock<rmutex> guard(m_header);
  512. //-------------------------------
  513. m_header.m_named_index.shrink_to_fit();
  514. m_header.m_unique_index.shrink_to_fit();
  515. }
  516. //!Returns the number of named objects stored in
  517. //!the segment.
  518. std::size_t get_num_named_objects()
  519. {
  520. //-------------------------------
  521. scoped_lock<rmutex> guard(m_header);
  522. //-------------------------------
  523. return m_header.m_named_index.size();
  524. }
  525. //!Returns the number of unique objects stored in
  526. //!the segment.
  527. std::size_t get_num_unique_objects()
  528. {
  529. //-------------------------------
  530. scoped_lock<rmutex> guard(m_header);
  531. //-------------------------------
  532. return m_header.m_unique_index.size();
  533. }
  534. //!Obtains the minimum size needed by the
  535. //!segment manager
  536. static std::size_t get_min_size()
  537. { return Base::get_min_size(priv_get_reserved_bytes()); }
  538. //!Returns a constant iterator to the beginning of the information about
  539. //!the named allocations performed in this segment manager
  540. const_named_iterator named_begin() const
  541. {
  542. return make_transform_iterator
  543. (m_header.m_named_index.begin(), named_transform());
  544. }
  545. //!Returns a constant iterator to the end of the information about
  546. //!the named allocations performed in this segment manager
  547. const_named_iterator named_end() const
  548. {
  549. return make_transform_iterator
  550. (m_header.m_named_index.end(), named_transform());
  551. }
  552. //!Returns a constant iterator to the beginning of the information about
  553. //!the unique allocations performed in this segment manager
  554. const_unique_iterator unique_begin() const
  555. {
  556. return make_transform_iterator
  557. (m_header.m_unique_index.begin(), unique_transform());
  558. }
  559. //!Returns a constant iterator to the end of the information about
  560. //!the unique allocations performed in this segment manager
  561. const_unique_iterator unique_end() const
  562. {
  563. return make_transform_iterator
  564. (m_header.m_unique_index.end(), unique_transform());
  565. }
  566. //!This is the default allocator to allocate types T
  567. //!from this managed segment
  568. template<class T>
  569. struct allocator
  570. {
  571. typedef boost::interprocess::allocator<T, segment_manager> type;
  572. };
  573. //!Returns an instance of the default allocator for type T
  574. //!initialized that allocates memory from this segment manager.
  575. template<class T>
  576. typename allocator<T>::type
  577. get_allocator()
  578. { return typename allocator<T>::type(this); }
  579. //!This is the default deleter to delete types T
  580. //!from this managed segment.
  581. template<class T>
  582. struct deleter
  583. {
  584. typedef boost::interprocess::deleter<T, segment_manager> type;
  585. };
  586. //!Returns an instance of the default allocator for type T
  587. //!initialized that allocates memory from this segment manager.
  588. template<class T>
  589. typename deleter<T>::type
  590. get_deleter()
  591. { return typename deleter<T>::type(this); }
  592. /// @cond
  593. //!Generic named/anonymous new function. Offers all the possibilities,
  594. //!such as throwing, search before creating, and the constructor is
  595. //!encapsulated in an object function.
  596. template<class T>
  597. T *generic_construct(const CharType *name,
  598. std::size_t num,
  599. bool try2find,
  600. bool dothrow,
  601. detail::in_place_interface &table)
  602. {
  603. return static_cast<T*>
  604. (priv_generic_construct(name, num, try2find, dothrow, table));
  605. }
  606. private:
  607. //!Tries to find a previous named allocation. Returns the address
  608. //!and the object count. On failure the first member of the
  609. //!returned pair is 0.
  610. template <class T>
  611. std::pair<T*, std::size_t> priv_find_impl (const CharType* name, bool lock)
  612. {
  613. //The name can't be null, no anonymous object can be found by name
  614. BOOST_ASSERT(name != 0);
  615. detail::placement_destroy<T> table;
  616. std::size_t size;
  617. void *ret;
  618. if(name == reinterpret_cast<const CharType*>(-1)){
  619. ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, size, is_intrusive_t(), lock);
  620. }
  621. else{
  622. ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, size, is_intrusive_t(), lock);
  623. }
  624. return std::pair<T*, std::size_t>(static_cast<T*>(ret), size);
  625. }
  626. //!Tries to find a previous unique allocation. Returns the address
  627. //!and the object count. On failure the first member of the
  628. //!returned pair is 0.
  629. template <class T>
  630. std::pair<T*, std::size_t> priv_find__impl (const detail::unique_instance_t* name, bool lock)
  631. {
  632. detail::placement_destroy<T> table;
  633. std::size_t size;
  634. void *ret = priv_generic_find<char>(name, m_header.m_unique_index, table, size, is_intrusive_t(), lock);
  635. return std::pair<T*, std::size_t>(static_cast<T*>(ret), size);
  636. }
  637. void *priv_generic_construct(const CharType *name,
  638. std::size_t num,
  639. bool try2find,
  640. bool dothrow,
  641. detail::in_place_interface &table)
  642. {
  643. void *ret;
  644. //Security overflow check
  645. if(num > ((std::size_t)-1)/table.size){
  646. if(dothrow)
  647. throw bad_alloc();
  648. else
  649. return 0;
  650. }
  651. if(name == 0){
  652. ret = this->prot_anonymous_construct(num, dothrow, table);
  653. }
  654. else if(name == reinterpret_cast<const CharType*>(-1)){
  655. ret = this->priv_generic_named_construct<char>
  656. (unique_type, table.type_name, num, try2find, dothrow, table, m_header.m_unique_index, is_intrusive_t());
  657. }
  658. else{
  659. ret = this->priv_generic_named_construct<CharType>
  660. (named_type, name, num, try2find, dothrow, table, m_header.m_named_index, is_intrusive_t());
  661. }
  662. return ret;
  663. }
  664. void priv_destroy_ptr(const void *ptr, detail::in_place_interface &dtor)
  665. {
  666. block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr, dtor.size, dtor.alignment);
  667. switch(ctrl_data->alloc_type()){
  668. case anonymous_type:
  669. this->prot_anonymous_destroy(ptr, dtor);
  670. break;
  671. case named_type:
  672. this->priv_generic_named_destroy<CharType>
  673. (ctrl_data, m_header.m_named_index, dtor, is_node_index_t());
  674. break;
  675. case unique_type:
  676. this->priv_generic_named_destroy<char>
  677. (ctrl_data, m_header.m_unique_index, dtor, is_node_index_t());
  678. break;
  679. default:
  680. //This type is unknown, bad pointer passed to this function!
  681. BOOST_ASSERT(0);
  682. break;
  683. }
  684. }
  685. //!Returns the name of an object created with construct/find_or_construct
  686. //!functions. Does not throw
  687. static const CharType *priv_get_instance_name(block_header_t *ctrl_data)
  688. {
  689. boost::interprocess::allocation_type type = ctrl_data->alloc_type();
  690. if(type != named_type){
  691. BOOST_ASSERT((type == anonymous_type && ctrl_data->m_num_char == 0) ||
  692. (type == unique_type && ctrl_data->m_num_char != 0) );
  693. return 0;
  694. }
  695. CharType *name = static_cast<CharType*>(ctrl_data->template name<CharType>());
  696. //Sanity checks
  697. BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharType));
  698. BOOST_ASSERT(ctrl_data->m_num_char == std::char_traits<CharType>::length(name));
  699. return name;
  700. }
  701. static std::size_t priv_get_instance_length(block_header_t *ctrl_data, std::size_t sizeofvalue)
  702. {
  703. //Get header
  704. BOOST_ASSERT((ctrl_data->value_bytes() %sizeofvalue) == 0);
  705. return ctrl_data->value_bytes()/sizeofvalue;
  706. }
  707. //!Returns is the the name of an object created with construct/find_or_construct
  708. //!functions. Does not throw
  709. static instance_type priv_get_instance_type(block_header_t *ctrl_data)
  710. {
  711. //Get header
  712. BOOST_ASSERT((instance_type)ctrl_data->alloc_type() < max_allocation_type);
  713. return (instance_type)ctrl_data->alloc_type();
  714. }
  715. static std::size_t priv_get_reserved_bytes()
  716. {
  717. //Get the number of bytes until the end of (*this)
  718. //beginning in the end of the Base base.
  719. return sizeof(segment_manager) - sizeof(Base);
  720. }
  721. template <class CharT>
  722. void *priv_generic_find
  723. (const CharT* name,
  724. IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
  725. detail::in_place_interface &table,
  726. std::size_t &length,
  727. detail::true_ is_intrusive,
  728. bool use_lock)
  729. {
  730. (void)is_intrusive;
  731. typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> > index_type;
  732. typedef detail::index_key<CharT, void_pointer> index_key_t;
  733. typedef typename index_type::iterator index_it;
  734. //-------------------------------
  735. scoped_lock<rmutex> guard(priv_get_lock(use_lock));
  736. //-------------------------------
  737. //Find name in index
  738. detail::intrusive_compare_key<CharT> key
  739. (name, std::char_traits<CharT>::length(name));
  740. index_it it = index.find(key);
  741. //Initialize return values
  742. void *ret_ptr = 0;
  743. length = 0;
  744. //If found, assign values
  745. if(it != index.end()){
  746. //Get header
  747. block_header_t *ctrl_data = it->get_block_header();
  748. //Sanity check
  749. BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
  750. BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT));
  751. ret_ptr = ctrl_data->value();
  752. length = ctrl_data->m_value_bytes/table.size;
  753. }
  754. return ret_ptr;
  755. }
  756. template <class CharT>
  757. void *priv_generic_find
  758. (const CharT* name,
  759. IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
  760. detail::in_place_interface &table,
  761. std::size_t &length,
  762. detail::false_ is_intrusive,
  763. bool use_lock)
  764. {
  765. (void)is_intrusive;
  766. typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> > index_type;
  767. typedef typename index_type::key_type key_type;
  768. typedef typename index_type::iterator index_it;
  769. //-------------------------------
  770. scoped_lock<rmutex> guard(priv_get_lock(use_lock));
  771. //-------------------------------
  772. //Find name in index
  773. index_it it = index.find(key_type(name, std::char_traits<CharT>::length(name)));
  774. //Initialize return values
  775. void *ret_ptr = 0;
  776. length = 0;
  777. //If found, assign values
  778. if(it != index.end()){
  779. //Get header
  780. block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
  781. (detail::get_pointer(it->second.m_ptr));
  782. //Sanity check
  783. BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
  784. BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT));
  785. ret_ptr = ctrl_data->value();
  786. length = ctrl_data->m_value_bytes/table.size;
  787. }
  788. return ret_ptr;
  789. }
  790. template <class CharT>
  791. bool priv_generic_named_destroy
  792. (block_header_t *block_header,
  793. IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
  794. detail::in_place_interface &table,
  795. detail::true_ is_node_index)
  796. {
  797. (void)is_node_index;
  798. typedef typename IndexType<detail::index_config<CharT, MemoryAlgorithm> >::iterator index_it;
  799. index_it *ihdr = block_header_t::to_first_header<index_it>(block_header);
  800. return this->priv_generic_named_destroy_impl<CharT>(*ihdr, index, table);
  801. }
  802. template <class CharT>
  803. bool priv_generic_named_destroy
  804. (block_header_t *block_header,
  805. IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
  806. detail::in_place_interface &table,
  807. detail::false_ is_node_index)
  808. {
  809. (void)is_node_index;
  810. CharT *name = static_cast<CharT*>(block_header->template name<CharT>());
  811. return this->priv_generic_named_destroy<CharT>(name, index, table, is_intrusive_t());
  812. }
  813. template <class CharT>
  814. bool priv_generic_named_destroy(const CharT *name,
  815. IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
  816. detail::in_place_interface &table,
  817. detail::true_ is_intrusive_index)
  818. {
  819. (void)is_intrusive_index;
  820. typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> > index_type;
  821. typedef detail::index_key<CharT, void_pointer> index_key_t;
  822. typedef typename index_type::iterator index_it;
  823. typedef typename index_type::value_type intrusive_value_type;
  824. //-------------------------------
  825. scoped_lock<rmutex> guard(m_header);
  826. //-------------------------------
  827. //Find name in index
  828. detail::intrusive_compare_key<CharT> key
  829. (name, std::char_traits<CharT>::length(name));
  830. index_it it = index.find(key);
  831. //If not found, return false
  832. if(it == index.end()){
  833. //This name is not present in the index, wrong pointer or name!
  834. //BOOST_ASSERT(0);
  835. return false;
  836. }
  837. block_header_t *ctrl_data = it->get_block_header();
  838. intrusive_value_type *iv = intrusive_value_type::get_intrusive_value_type(ctrl_data);
  839. void *memory = iv;
  840. void *values = ctrl_data->value();
  841. std::size_t num = ctrl_data->m_value_bytes/table.size;
  842. //Sanity check
  843. BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
  844. BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
  845. //Erase node from index
  846. index.erase(it);
  847. //Destroy the headers
  848. ctrl_data->~block_header_t();
  849. iv->~intrusive_value_type();
  850. //Call destructors and free memory
  851. std::size_t destroyed;
  852. table.destroy_n(values, num, destroyed);
  853. this->deallocate(memory);
  854. return true;
  855. }
  856. template <class CharT>
  857. bool priv_generic_named_destroy(const CharT *name,
  858. IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
  859. detail::in_place_interface &table,
  860. detail::false_ is_intrusive_index)
  861. {
  862. (void)is_intrusive_index;
  863. typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> > index_type;
  864. typedef typename index_type::iterator index_it;
  865. typedef typename index_type::key_type key_type;
  866. //-------------------------------
  867. scoped_lock<rmutex> guard(m_header);
  868. //-------------------------------
  869. //Try to find the name in the index
  870. index_it it = index.find(key_type (name,
  871. std::char_traits<CharT>::length(name)));
  872. //If not found, return false
  873. if(it == index.end()){
  874. //This name is not present in the index, wrong pointer or name!
  875. //BOOST_ASSERT(0);
  876. return false;
  877. }
  878. return this->priv_generic_named_destroy_impl<CharT>(it, index, table);
  879. }
  880. template <class CharT>
  881. bool priv_generic_named_destroy_impl
  882. (const typename IndexType<detail::index_config<CharT, MemoryAlgorithm> >::iterator &it,
  883. IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
  884. detail::in_place_interface &table)
  885. {
  886. typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> > index_type;
  887. typedef typename index_type::iterator index_it;
  888. //Get allocation parameters
  889. block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
  890. (detail::get_pointer(it->second.m_ptr));
  891. char *stored_name = static_cast<char*>(static_cast<void*>(const_cast<CharT*>(it->first.name())));
  892. (void)stored_name;
  893. //Check if the distance between the name pointer and the memory pointer
  894. //is correct (this can detect incorrect type in destruction)
  895. std::size_t num = ctrl_data->m_value_bytes/table.size;
  896. void *values = ctrl_data->value();
  897. //Sanity check
  898. BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
  899. BOOST_ASSERT(static_cast<void*>(stored_name) == static_cast<void*>(ctrl_data->template name<CharT>()));
  900. BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
  901. //Erase node from index
  902. index.erase(it);
  903. //Destroy the header
  904. ctrl_data->~block_header_t();
  905. void *memory;
  906. if(is_node_index_t::value){
  907. index_it *ihdr = block_header_t::
  908. to_first_header<index_it>(ctrl_data);
  909. ihdr->~index_it();
  910. memory = ihdr;
  911. }
  912. else{
  913. memory = ctrl_data;
  914. }
  915. //Call destructors and free memory
  916. std::size_t destroyed;
  917. table.destroy_n(values, num, destroyed);
  918. this->deallocate(memory);
  919. return true;
  920. }
  921. template<class CharT>
  922. void * priv_generic_named_construct(std::size_t type,
  923. const CharT *name,
  924. std::size_t num,
  925. bool try2find,
  926. bool dothrow,
  927. detail::in_place_interface &table,
  928. IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
  929. detail::true_ is_intrusive)
  930. {
  931. (void)is_intrusive;
  932. std::size_t namelen = std::char_traits<CharT>::length(name);
  933. block_header_t block_info ( table.size*num
  934. , table.alignment
  935. , type
  936. , sizeof(CharT)
  937. , namelen);
  938. typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> > index_type;
  939. typedef typename index_type::iterator index_it;
  940. typedef std::pair<index_it, bool> index_ib;
  941. //-------------------------------
  942. scoped_lock<rmutex> guard(m_header);
  943. //-------------------------------
  944. //Insert the node. This can throw.
  945. //First, we want to know if the key is already present before
  946. //we allocate any memory, and if the key is not present, we
  947. //want to allocate all memory in a single buffer that will
  948. //contain the name and the user buffer.
  949. //
  950. //Since equal_range(key) + insert(hint, value) approach is
  951. //quite inefficient in container implementations
  952. //(they re-test if the position is correct), I've chosen
  953. //to insert the node, do an ugly un-const cast and modify
  954. //the key (which is a smart pointer) to an equivalent one
  955. index_ib insert_ret;
  956. typename index_type::insert_commit_data commit_data;
  957. typedef typename index_type::value_type intrusive_value_type;
  958. BOOST_TRY{
  959. detail::intrusive_compare_key<CharT> key(name, namelen);
  960. insert_ret = index.insert_check(key, commit_data);
  961. }
  962. //Ignore exceptions
  963. BOOST_CATCH(...){
  964. if(dothrow)
  965. BOOST_RETHROW
  966. return 0;
  967. }
  968. BOOST_CATCH_END
  969. index_it it = insert_ret.first;
  970. //If found and this is find or construct, return data
  971. //else return null
  972. if(!insert_ret.second){
  973. if(try2find){
  974. return it->get_block_header()->value();
  975. }
  976. if(dothrow){
  977. throw interprocess_exception(already_exists_error);
  978. }
  979. else{
  980. return 0;
  981. }
  982. }
  983. //Allocates buffer for name + data, this can throw (it hurts)
  984. void *buffer_ptr;
  985. //Check if there is enough memory
  986. if(dothrow){
  987. buffer_ptr = this->allocate
  988. (block_info.total_size_with_header<intrusive_value_type>());
  989. }
  990. else{
  991. buffer_ptr = this->allocate
  992. (block_info.total_size_with_header<intrusive_value_type>(), std::nothrow_t());
  993. if(!buffer_ptr)
  994. return 0;
  995. }
  996. //Now construct the intrusive hook plus the header
  997. intrusive_value_type * intrusive_hdr = new(buffer_ptr) intrusive_value_type();
  998. block_header_t * hdr = new(intrusive_hdr->get_block_header())block_header_t(block_info);
  999. void *ptr = 0; //avoid gcc warning
  1000. ptr = hdr->value();
  1001. //Copy name to memory segment and insert data
  1002. CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
  1003. std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
  1004. BOOST_TRY{
  1005. //Now commit the insertion using previous context data
  1006. it = index.insert_commit(*intrusive_hdr, commit_data);
  1007. }
  1008. //Ignore exceptions
  1009. BOOST_CATCH(...){
  1010. if(dothrow)
  1011. BOOST_RETHROW
  1012. return 0;
  1013. }
  1014. BOOST_CATCH_END
  1015. //Avoid constructions if constructor is trivial
  1016. //Build scoped ptr to avoid leaks with constructor exception
  1017. detail::mem_algo_deallocator<segment_manager_base_type> mem
  1018. (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
  1019. //Initialize the node value_eraser to erase inserted node
  1020. //if something goes wrong. This will be executed *before*
  1021. //the memory allocation as the intrusive value is built in that
  1022. //memory
  1023. value_eraser<index_type> v_eraser(index, it);
  1024. //Construct array, this can throw
  1025. detail::array_construct(ptr, num, table);
  1026. //Release rollbacks since construction was successful
  1027. v_eraser.release();
  1028. mem.release();
  1029. return ptr;
  1030. }
  1031. //!Generic named new function for
  1032. //!named functions
  1033. template<class CharT>
  1034. void * priv_generic_named_construct(std::size_t type,
  1035. const CharT *name,
  1036. std::size_t num,
  1037. bool try2find,
  1038. bool dothrow,
  1039. detail::in_place_interface &table,
  1040. IndexType<detail::index_config<CharT, MemoryAlgorithm> > &index,
  1041. detail::false_ is_intrusive)
  1042. {
  1043. (void)is_intrusive;
  1044. std::size_t namelen = std::char_traits<CharT>::length(name);
  1045. block_header_t block_info ( table.size*num
  1046. , table.alignment
  1047. , type
  1048. , sizeof(CharT)
  1049. , namelen);
  1050. typedef IndexType<detail::index_config<CharT, MemoryAlgorithm> > index_type;
  1051. typedef typename index_type::key_type key_type;
  1052. typedef typename index_type::mapped_type mapped_type;
  1053. typedef typename index_type::value_type value_type;
  1054. typedef typename index_type::iterator index_it;
  1055. typedef std::pair<index_it, bool> index_ib;
  1056. //-------------------------------
  1057. scoped_lock<rmutex> guard(m_header);
  1058. //-------------------------------
  1059. //Insert the node. This can throw.
  1060. //First, we want to know if the key is already present before
  1061. //we allocate any memory, and if the key is not present, we
  1062. //want to allocate all memory in a single buffer that will
  1063. //contain the name and the user buffer.
  1064. //
  1065. //Since equal_range(key) + insert(hint, value) approach is
  1066. //quite inefficient in container implementations
  1067. //(they re-test if the position is correct), I've chosen
  1068. //to insert the node, do an ugly un-const cast and modify
  1069. //the key (which is a smart pointer) to an equivalent one
  1070. index_ib insert_ret;
  1071. BOOST_TRY{
  1072. insert_ret = index.insert(value_type(key_type (name, namelen), mapped_type(0)));
  1073. }
  1074. //Ignore exceptions
  1075. BOOST_CATCH(...){
  1076. if(dothrow)
  1077. BOOST_RETHROW;
  1078. return 0;
  1079. }
  1080. BOOST_CATCH_END
  1081. index_it it = insert_ret.first;
  1082. //If found and this is find or construct, return data
  1083. //else return null
  1084. if(!insert_ret.second){
  1085. if(try2find){
  1086. block_header_t *hdr = static_cast<block_header_t*>
  1087. (detail::get_pointer(it->second.m_ptr));
  1088. return hdr->value();
  1089. }
  1090. return 0;
  1091. }
  1092. //Initialize the node value_eraser to erase inserted node
  1093. //if something goes wrong
  1094. value_eraser<index_type> v_eraser(index, it);
  1095. //Allocates buffer for name + data, this can throw (it hurts)
  1096. void *buffer_ptr;
  1097. block_header_t * hdr;
  1098. //Allocate and construct the headers
  1099. if(is_node_index_t::value){
  1100. std::size_t total_size = block_info.total_size_with_header<index_it>();
  1101. if(dothrow){
  1102. buffer_ptr = this->allocate(total_size);
  1103. }
  1104. else{
  1105. buffer_ptr = this->allocate(total_size, std::nothrow_t());
  1106. if(!buffer_ptr)
  1107. return 0;
  1108. }
  1109. index_it *idr = new(buffer_ptr) index_it(it);
  1110. hdr = block_header_t::from_first_header<index_it>(idr);
  1111. }
  1112. else{
  1113. if(dothrow){
  1114. buffer_ptr = this->allocate(block_info.total_size());
  1115. }
  1116. else{
  1117. buffer_ptr = this->allocate(block_info.total_size(), std::nothrow_t());
  1118. if(!buffer_ptr)
  1119. return 0;
  1120. }
  1121. hdr = static_cast<block_header_t*>(buffer_ptr);
  1122. }
  1123. hdr = new(hdr)block_header_t(block_info);
  1124. void *ptr = 0; //avoid gcc warning
  1125. ptr = hdr->value();
  1126. //Copy name to memory segment and insert data
  1127. CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
  1128. std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
  1129. //Do the ugly cast, please mama, forgive me!
  1130. //This new key points to an identical string, so it must have the
  1131. //same position than the overwritten key according to the predicate
  1132. const_cast<key_type &>(it->first).name(name_ptr);
  1133. it->second.m_ptr = hdr;
  1134. //Build scoped ptr to avoid leaks with constructor exception
  1135. detail::mem_algo_deallocator<segment_manager_base_type> mem
  1136. (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
  1137. //Construct array, this can throw
  1138. detail::array_construct(ptr, num, table);
  1139. //All constructors successful, we don't want to release memory
  1140. mem.release();
  1141. //Release node v_eraser since construction was successful
  1142. v_eraser.release();
  1143. return ptr;
  1144. }
  1145. private:
  1146. //!Returns the this pointer
  1147. segment_manager *get_this_pointer()
  1148. { return this; }
  1149. typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex;
  1150. scoped_lock<rmutex> priv_get_lock(bool use_lock)
  1151. {
  1152. scoped_lock<rmutex> local(m_header, defer_lock);
  1153. if(use_lock){
  1154. local.lock();
  1155. }
  1156. return scoped_lock<rmutex>(boost::interprocess::move(local));
  1157. }
  1158. //!This struct includes needed data and derives from
  1159. //!rmutex to allow EBO when using null interprocess_mutex
  1160. struct header_t
  1161. : public rmutex
  1162. {
  1163. named_index_t m_named_index;
  1164. unique_index_t m_unique_index;
  1165. header_t(Base *restricted_segment_mngr)
  1166. : m_named_index (restricted_segment_mngr)
  1167. , m_unique_index(restricted_segment_mngr)
  1168. {}
  1169. } m_header;
  1170. /// @endcond
  1171. };
  1172. }} //namespace boost { namespace interprocess
  1173. #include <boost/interprocess/detail/config_end.hpp>
  1174. #endif //#ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP