managed_memory_impl.hpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775
  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_DETAIL_MANAGED_MEMORY_IMPL_HPP
  11. #define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_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/interprocess_fwd.hpp>
  22. #include <boost/interprocess/detail/utilities.hpp>
  23. #include <boost/interprocess/detail/os_file_functions.hpp>
  24. #include <boost/interprocess/creation_tags.hpp>
  25. #include <boost/interprocess/exceptions.hpp>
  26. #include <boost/interprocess/segment_manager.hpp>
  27. #include <boost/interprocess/sync/scoped_lock.hpp>
  28. #include <boost/interprocess/detail/nothrow.hpp>
  29. #include <boost/interprocess/detail/simple_swap.hpp>
  30. //
  31. //
  32. #include <boost/intrusive/detail/minimal_pair_header.hpp>
  33. #include <boost/assert.hpp>
  34. //!\file
  35. //!Describes a named shared memory allocation user class.
  36. //!
  37. namespace boost {
  38. namespace interprocess {
  39. namespace ipcdetail {
  40. template<class BasicManagedMemoryImpl>
  41. class create_open_func;
  42. template<
  43. class CharType,
  44. class MemoryAlgorithm,
  45. template<class IndexConfig> class IndexType
  46. >
  47. struct segment_manager_type
  48. {
  49. typedef segment_manager<CharType, MemoryAlgorithm, IndexType> type;
  50. };
  51. //!This class is designed to be a base class to classes that manage
  52. //!creation of objects in a fixed size memory buffer. Apart
  53. //!from allocating raw memory, the user can construct named objects. To
  54. //!achieve this, this class uses the reserved space provided by the allocation
  55. //!algorithm to place a named_allocator_algo, who takes care of name mappings.
  56. //!The class can be customized with the char type used for object names
  57. //!and the memory allocation algorithm to be used.*/
  58. template < class CharType
  59. , class MemoryAlgorithm
  60. , template<class IndexConfig> class IndexType
  61. , std::size_t Offset = 0
  62. >
  63. class basic_managed_memory_impl
  64. {
  65. //Non-copyable
  66. basic_managed_memory_impl(const basic_managed_memory_impl &);
  67. basic_managed_memory_impl &operator=(const basic_managed_memory_impl &);
  68. template<class BasicManagedMemoryImpl>
  69. friend class create_open_func;
  70. public:
  71. typedef typename segment_manager_type
  72. <CharType, MemoryAlgorithm, IndexType>::type segment_manager;
  73. typedef CharType char_type;
  74. typedef MemoryAlgorithm memory_algorithm;
  75. typedef typename MemoryAlgorithm::mutex_family mutex_family;
  76. typedef CharType char_t;
  77. typedef typename MemoryAlgorithm::size_type size_type;
  78. typedef typename MemoryAlgorithm::difference_type difference_type;
  79. typedef difference_type handle_t;
  80. typedef typename segment_manager::
  81. const_named_iterator const_named_iterator;
  82. typedef typename segment_manager::
  83. const_unique_iterator const_unique_iterator;
  84. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  85. typedef typename
  86. segment_manager::char_ptr_holder_t char_ptr_holder_t;
  87. //Experimental. Don't use.
  88. typedef typename segment_manager::multiallocation_chain multiallocation_chain;
  89. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  90. static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation;
  91. private:
  92. typedef basic_managed_memory_impl
  93. <CharType, MemoryAlgorithm, IndexType, Offset> self_t;
  94. protected:
  95. template<class ManagedMemory, class CharT>
  96. static bool grow(const CharT *filename, size_type extra_bytes)
  97. {
  98. typedef typename ManagedMemory::device_type device_type;
  99. //Increase file size
  100. BOOST_INTERPROCESS_TRY{
  101. offset_t old_size;
  102. {
  103. device_type f(open_or_create, filename, read_write);
  104. if(!f.get_size(old_size))
  105. return false;
  106. f.truncate(old_size + static_cast<offset_t>(extra_bytes));
  107. }
  108. ManagedMemory managed_memory(open_only, filename);
  109. //Grow always works
  110. managed_memory.self_t::grow(extra_bytes);
  111. }
  112. BOOST_INTERPROCESS_CATCH(...){
  113. return false;
  114. } BOOST_INTERPROCESS_CATCH_END
  115. return true;
  116. }
  117. template<class ManagedMemory, class CharT>
  118. static bool shrink_to_fit(const CharT *filename)
  119. {
  120. typedef typename ManagedMemory::device_type device_type;
  121. size_type new_size;
  122. BOOST_INTERPROCESS_TRY{
  123. ManagedMemory managed_memory(open_only, filename);
  124. managed_memory.get_size();
  125. managed_memory.self_t::shrink_to_fit();
  126. new_size = managed_memory.get_size();
  127. }
  128. BOOST_INTERPROCESS_CATCH(...){
  129. return false;
  130. } BOOST_INTERPROCESS_CATCH_END
  131. //Decrease file size
  132. {
  133. device_type f(open_or_create, filename, read_write);
  134. f.truncate(static_cast<offset_t>(new_size));
  135. }
  136. return true;
  137. }
  138. //!Constructor. Allocates basic resources. Never throws.
  139. basic_managed_memory_impl()
  140. : mp_header(0){}
  141. //!Destructor. Calls close. Never throws.
  142. ~basic_managed_memory_impl()
  143. { this->close_impl(); }
  144. //!Places segment manager in the reserved space. This can throw.
  145. bool create_impl (void *addr, size_type size)
  146. {
  147. if(mp_header) return false;
  148. //Check if there is enough space
  149. if(size < segment_manager::get_min_size())
  150. return false;
  151. //This function should not throw. The index construction can
  152. //throw if constructor allocates memory. So we must catch it.
  153. BOOST_INTERPROCESS_TRY{
  154. //Let's construct the allocator in memory
  155. BOOST_ASSERT((0 == (std::size_t)addr % boost::move_detail::alignment_of<segment_manager>::value));
  156. mp_header = ::new(addr, boost_container_new_t()) segment_manager(size);
  157. }
  158. BOOST_INTERPROCESS_CATCH(...){
  159. return false;
  160. } BOOST_INTERPROCESS_CATCH_END
  161. return true;
  162. }
  163. //!Connects to a segment manager in the reserved buffer. Never throws.
  164. bool open_impl (void *addr, size_type)
  165. {
  166. if(mp_header) return false;
  167. mp_header = static_cast<segment_manager*>(addr);
  168. return true;
  169. }
  170. //!Frees resources. Never throws.
  171. bool close_impl()
  172. {
  173. bool ret = mp_header != 0;
  174. mp_header = 0;
  175. return ret;
  176. }
  177. //!Frees resources and destroys common resources. Never throws.
  178. bool destroy_impl()
  179. {
  180. if(mp_header == 0)
  181. return false;
  182. mp_header->~segment_manager();
  183. this->close_impl();
  184. return true;
  185. }
  186. //!
  187. void grow(size_type extra_bytes)
  188. { mp_header->grow(extra_bytes); }
  189. void shrink_to_fit()
  190. { mp_header->shrink_to_fit(); }
  191. public:
  192. //!Returns segment manager. Never throws.
  193. segment_manager *get_segment_manager() const
  194. { return mp_header; }
  195. //!Returns the base address of the memory in this process. Never throws.
  196. void * get_address () const
  197. { return reinterpret_cast<char*>(mp_header) - Offset; }
  198. //!Returns the size of memory segment. Never throws.
  199. size_type get_size () const
  200. { return mp_header->get_size() + Offset; }
  201. //!Returns the number of free bytes of the memory
  202. //!segment
  203. size_type get_free_memory() const
  204. { return mp_header->get_free_memory(); }
  205. //!Returns the result of "all_memory_deallocated()" function
  206. //!of the used memory algorithm
  207. bool all_memory_deallocated()
  208. { return mp_header->all_memory_deallocated(); }
  209. //!Returns the result of "check_sanity()" function
  210. //!of the used memory algorithm
  211. bool check_sanity()
  212. { return mp_header->check_sanity(); }
  213. //!Writes to zero free memory (memory not yet allocated) of
  214. //!the memory algorithm
  215. void zero_free_memory()
  216. { mp_header->zero_free_memory(); }
  217. //!Transforms an absolute address into an offset from base address.
  218. //!The address must belong to the memory segment. Never throws.
  219. handle_t get_handle_from_address (const void *ptr) const
  220. {
  221. return (handle_t)(reinterpret_cast<const char*>(ptr) -
  222. reinterpret_cast<const char*>(this->get_address()));
  223. }
  224. //!Returns true if the address belongs to the managed memory segment
  225. bool belongs_to_segment (const void *ptr) const
  226. {
  227. return ptr >= this->get_address() &&
  228. ptr < (reinterpret_cast<const char*>(this->get_address()) + this->get_size());
  229. }
  230. //!Transforms previously obtained offset into an absolute address in the
  231. //!process space of the current process. Never throws.*/
  232. void * get_address_from_handle (handle_t offset) const
  233. { return reinterpret_cast<char*>(this->get_address()) + offset; }
  234. //!Searches for nbytes of free memory in the segment, marks the
  235. //!memory as used and return the pointer to the memory. If no
  236. //!memory is available throws a boost::interprocess::bad_alloc exception
  237. void* allocate (size_type nbytes)
  238. { return mp_header->allocate(nbytes); }
  239. //!Searches for nbytes of free memory in the segment, marks the
  240. //!memory as used and return the pointer to the memory. If no memory
  241. //!is available returns 0. Never throws.
  242. void* allocate (size_type nbytes, const std::nothrow_t &tag)
  243. { return mp_header->allocate(nbytes, tag); }
  244. //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
  245. //!must be power of two. If no memory
  246. //!is available returns 0. Never throws.
  247. void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &tag)
  248. { return mp_header->allocate_aligned(nbytes, alignment, tag); }
  249. template<class T>
  250. T * allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
  251. size_type &prefer_in_recvd_out_size, T *&reuse)
  252. { return mp_header->allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); }
  253. //!Allocates nbytes bytes aligned to "alignment" bytes. "alignment"
  254. //!must be power of two. If no
  255. //!memory is available throws a boost::interprocess::bad_alloc exception
  256. void * allocate_aligned(size_type nbytes, size_type alignment)
  257. { return mp_header->allocate_aligned(nbytes, alignment); }
  258. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  259. //Experimental. Don't use.
  260. //!Allocates n_elements of elem_bytes bytes.
  261. //!Throws bad_alloc on failure. chain.size() is not increased on failure.
  262. void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
  263. { mp_header->allocate_many(elem_bytes, n_elements, chain); }
  264. //!Allocates n_elements, each one of element_lengths[i]*sizeof_element bytes.
  265. //!Throws bad_alloc on failure. chain.size() is not increased on failure.
  266. void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
  267. { mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); }
  268. //!Allocates n_elements of elem_bytes bytes.
  269. //!Non-throwing version. chain.size() is not increased on failure.
  270. void allocate_many(const std::nothrow_t &tag, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
  271. { mp_header->allocate_many(tag, elem_bytes, n_elements, chain); }
  272. //!Allocates n_elements, each one of
  273. //!element_lengths[i]*sizeof_element bytes.
  274. //!Non-throwing version. chain.size() is not increased on failure.
  275. void allocate_many(const std::nothrow_t &tag, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
  276. { mp_header->allocate_many(tag, elem_sizes, n_elements, sizeof_element, chain); }
  277. //!Deallocates all elements contained in chain.
  278. //!Never throws.
  279. void deallocate_many(multiallocation_chain &chain)
  280. { mp_header->deallocate_many(chain); }
  281. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  282. //!Marks previously allocated memory as free. Never throws.
  283. void deallocate (void *addr)
  284. { if (mp_header) mp_header->deallocate(addr); }
  285. //!Tries to find a previous named allocation address. Returns a memory
  286. //!buffer and the object count. If not found returned pointer is 0.
  287. //!Never throws.
  288. template <class T>
  289. std::pair<T*, size_type> find (char_ptr_holder_t name)
  290. { return mp_header->template find<T>(name); }
  291. //!Creates a named object or array in memory
  292. //!
  293. //!Allocates and constructs a T object or an array of T in memory,
  294. //!associates this with the given name and returns a pointer to the
  295. //!created object. If an array is being constructed all objects are
  296. //!created using the same parameters given to this function.
  297. //!
  298. //!-> If the name was previously used, returns 0.
  299. //!
  300. //!-> Throws boost::interprocess::bad_alloc if there is no available memory
  301. //!
  302. //!-> If T's constructor throws, the function throws that exception.
  303. //!
  304. //!Memory is freed automatically if T's constructor throws and if an
  305. //!array was being constructed, destructors of created objects are called
  306. //!before freeing the memory.
  307. template <class T>
  308. typename segment_manager::template construct_proxy<T>::type
  309. construct(char_ptr_holder_t name)
  310. { return mp_header->template construct<T>(name); }
  311. //!Finds or creates a named object or array in memory
  312. //!
  313. //!Tries to find an object with the given name in memory. If
  314. //!found, returns the pointer to this pointer. If the object is not found,
  315. //!allocates and constructs a T object or an array of T in memory,
  316. //!associates this with the given name and returns a pointer to the
  317. //!created object. If an array is being constructed all objects are
  318. //!created using the same parameters given to this function.
  319. //!
  320. //!-> Throws boost::interprocess::bad_alloc if there is no available memory
  321. //!
  322. //!-> If T's constructor throws, the function throws that exception.
  323. //!
  324. //!Memory is freed automatically if T's constructor throws and if an
  325. //!array was being constructed, destructors of created objects are called
  326. //!before freeing the memory.
  327. template <class T>
  328. typename segment_manager::template construct_proxy<T>::type
  329. find_or_construct(char_ptr_holder_t name)
  330. { return mp_header->template find_or_construct<T>(name); }
  331. //!Creates a named object or array in memory
  332. //!
  333. //!Allocates and constructs a T object or an array of T in memory,
  334. //!associates this with the given name and returns a pointer to the
  335. //!created object. If an array is being constructed all objects are
  336. //!created using the same parameters given to this function.
  337. //!
  338. //!-> If the name was previously used, returns 0.
  339. //!
  340. //!-> Returns 0 if there is no available memory
  341. //!
  342. //!-> If T's constructor throws, the function throws that exception.
  343. //!
  344. //!Memory is freed automatically if T's constructor throws and if an
  345. //!array was being constructed, destructors of created objects are called
  346. //!before freeing the memory.
  347. template <class T>
  348. typename segment_manager::template construct_proxy<T>::type
  349. construct(char_ptr_holder_t name, const std::nothrow_t &tag)
  350. { return mp_header->template construct<T>(name, tag); }
  351. //!Finds or creates a named object or array in memory
  352. //!
  353. //!Tries to find an object with the given name in memory. If
  354. //!found, returns the pointer to this pointer. If the object is not found,
  355. //!allocates and constructs a T object or an array of T in memory,
  356. //!associates this with the given name and returns a pointer to the
  357. //!created object. If an array is being constructed all objects are
  358. //!created using the same parameters given to this function.
  359. //!
  360. //!-> Returns 0 if there is no available memory
  361. //!
  362. //!-> If T's constructor throws, the function throws that exception.
  363. //!
  364. //!Memory is freed automatically if T's constructor throws and if an
  365. //!array was being constructed, destructors of created objects are called
  366. //!before freeing the memory.
  367. template <class T>
  368. typename segment_manager::template construct_proxy<T>::type
  369. find_or_construct(char_ptr_holder_t name, const std::nothrow_t &tag)
  370. { return mp_header->template find_or_construct<T>(name, tag); }
  371. //!Creates a named array from iterators in memory
  372. //!
  373. //!Allocates and constructs an array of T in memory,
  374. //!associates this with the given name and returns a pointer to the
  375. //!created object. Each element in the array is created using the
  376. //!objects returned when dereferencing iterators as parameters
  377. //!and incrementing all iterators for each element.
  378. //!
  379. //!-> If the name was previously used, returns 0.
  380. //!
  381. //!-> Throws boost::interprocess::bad_alloc if there is no available memory
  382. //!
  383. //!-> If T's constructor throws, the function throws that exception.
  384. //!
  385. //!Memory is freed automatically if T's constructor throws and
  386. //!destructors of created objects are called before freeing the memory.
  387. template <class T>
  388. typename segment_manager::template construct_iter_proxy<T>::type
  389. construct_it(char_ptr_holder_t name)
  390. { return mp_header->template construct_it<T>(name); }
  391. //!Finds or creates a named array from iterators in memory
  392. //!
  393. //!Tries to find an object with the given name in memory. If
  394. //!found, returns the pointer to this pointer. If the object is not found,
  395. //!allocates and constructs an array of T in memory,
  396. //!associates this with the given name and returns a pointer to the
  397. //!created object. Each element in the array is created using the
  398. //!objects returned when dereferencing iterators as parameters
  399. //!and incrementing all iterators for each element.
  400. //!
  401. //!-> If the name was previously used, returns 0.
  402. //!
  403. //!-> Throws boost::interprocess::bad_alloc if there is no available memory
  404. //!
  405. //!-> If T's constructor throws, the function throws that exception.
  406. //!
  407. //!Memory is freed automatically if T's constructor throws and
  408. //!destructors of created objects are called before freeing the memory.
  409. template <class T>
  410. typename segment_manager::template construct_iter_proxy<T>::type
  411. find_or_construct_it(char_ptr_holder_t name)
  412. { return mp_header->template find_or_construct_it<T>(name); }
  413. //!Creates a named array from iterators in memory
  414. //!
  415. //!Allocates and constructs an array of T in memory,
  416. //!associates this with the given name and returns a pointer to the
  417. //!created object. Each element in the array is created using the
  418. //!objects returned when dereferencing iterators as parameters
  419. //!and incrementing all iterators for each element.
  420. //!
  421. //!-> If the name was previously used, returns 0.
  422. //!
  423. //!-> If there is no available memory, returns 0.
  424. //!
  425. //!-> If T's constructor throws, the function throws that exception.
  426. //!
  427. //!Memory is freed automatically if T's constructor throws and
  428. //!destructors of created objects are called before freeing the memory.*/
  429. template <class T>
  430. typename segment_manager::template construct_iter_proxy<T>::type
  431. construct_it(char_ptr_holder_t name, const std::nothrow_t &tag)
  432. { return mp_header->template construct_it<T>(name, tag); }
  433. //!Finds or creates a named array from iterators in memory
  434. //!
  435. //!Tries to find an object with the given name in memory. If
  436. //!found, returns the pointer to this pointer. If the object is not found,
  437. //!allocates and constructs an array of T in memory,
  438. //!associates this with the given name and returns a pointer to the
  439. //!created object. Each element in the array is created using the
  440. //!objects returned when dereferencing iterators as parameters
  441. //!and incrementing all iterators for each element.
  442. //!
  443. //!-> If the name was previously used, returns 0.
  444. //!
  445. //!-> If there is no available memory, returns 0.
  446. //!
  447. //!-> If T's constructor throws, the function throws that exception.
  448. //!
  449. //!Memory is freed automatically if T's constructor throws and
  450. //!destructors of created objects are called before freeing the memory.*/
  451. template <class T>
  452. typename segment_manager::template construct_iter_proxy<T>::type
  453. find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &tag)
  454. { return mp_header->template find_or_construct_it<T>(name, tag); }
  455. //!Calls a functor and guarantees that no new construction, search or
  456. //!destruction will be executed by any process while executing the object
  457. //!function call. If the functor throws, this function throws.
  458. template <class Func>
  459. void atomic_func(Func &f)
  460. { mp_header->atomic_func(f); }
  461. //!Tries to call a functor guaranteeing that no new construction, search or
  462. //!destruction will be executed by any process while executing the object
  463. //!function call. If the atomic function can't be immediatelly executed
  464. //!because the internal mutex is already locked, returns false.
  465. //!If the functor throws, this function throws.
  466. template <class Func>
  467. bool try_atomic_func(Func &f)
  468. { return mp_header->try_atomic_func(f); }
  469. //!Destroys a named memory object or array.
  470. //!
  471. //!Finds the object with the given name, calls its destructors,
  472. //!frees used memory and returns true.
  473. //!
  474. //!-> If the object is not found, it returns false.
  475. //!
  476. //!Exception Handling:
  477. //!
  478. //!When deleting a dynamically object or array, the Standard
  479. //!does not guarantee that dynamically allocated memory, will be released.
  480. //!Also, when deleting arrays, the Standard doesn't require calling
  481. //!destructors for the rest of the objects if for one of them the destructor
  482. //!terminated with an exception.
  483. //!
  484. //!Destroying an object:
  485. //!
  486. //!If the destructor throws, the memory will be freed and that exception
  487. //!will be thrown.
  488. //!
  489. //!Destroying an array:
  490. //!
  491. //!When destroying an array, if a destructor throws, the rest of
  492. //!destructors are called. If any of these throws, the exceptions are
  493. //!ignored. The name association will be erased, memory will be freed and
  494. //!the first exception will be thrown. This guarantees the unlocking of
  495. //!mutexes and other resources.
  496. //!
  497. //!For all theses reasons, classes with throwing destructors are not
  498. //!recommended.
  499. template <class T>
  500. bool destroy(const CharType *name)
  501. { return mp_header->template destroy<T>(name); }
  502. //!Destroys the unique instance of type T
  503. //!
  504. //!Calls the destructor, frees used memory and returns true.
  505. //!
  506. //!Exception Handling:
  507. //!
  508. //!When deleting a dynamically object, the Standard does not
  509. //!guarantee that dynamically allocated memory will be released.
  510. //!
  511. //!Destroying an object:
  512. //!
  513. //!If the destructor throws, the memory will be freed and that exception
  514. //!will be thrown.
  515. //!
  516. //!For all theses reasons, classes with throwing destructors are not
  517. //!recommended for memory.
  518. template <class T>
  519. bool destroy(const unique_instance_t *const )
  520. { return mp_header->template destroy<T>(unique_instance); }
  521. //!Destroys the object (named, unique, or anonymous)
  522. //!
  523. //!Calls the destructor, frees used memory and returns true.
  524. //!
  525. //!Exception Handling:
  526. //!
  527. //!When deleting a dynamically object, the Standard does not
  528. //!guarantee that dynamically allocated memory will be released.
  529. //!
  530. //!Destroying an object:
  531. //!
  532. //!If the destructor throws, the memory will be freed and that exception
  533. //!will be thrown.
  534. //!
  535. //!For all theses reasons, classes with throwing destructors are not
  536. //!recommended for memory.
  537. template <class T>
  538. void destroy_ptr(const T *ptr)
  539. { mp_header->template destroy_ptr<T>(ptr); }
  540. //!Returns the name of an object created with construct/find_or_construct
  541. //!functions. If ptr points to an unique instance typeid(T).name() is returned.
  542. template<class T>
  543. static const char_type *get_instance_name(const T *ptr)
  544. { return segment_manager::get_instance_name(ptr); }
  545. //!Returns is the type an object created with construct/find_or_construct
  546. //!functions. Does not throw.
  547. template<class T>
  548. static instance_type get_instance_type(const T *ptr)
  549. { return segment_manager::get_instance_type(ptr); }
  550. //!Returns the length of an object created with construct/find_or_construct
  551. //!functions (1 if is a single element, >=1 if it's an array). Does not throw.
  552. template<class T>
  553. static size_type get_instance_length(const T *ptr)
  554. { return segment_manager::get_instance_length(ptr); }
  555. //!Preallocates needed index resources to optimize the
  556. //!creation of "num" named objects in the memory segment.
  557. //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
  558. void reserve_named_objects(size_type num)
  559. { mp_header->reserve_named_objects(num); }
  560. //!Preallocates needed index resources to optimize the
  561. //!creation of "num" unique objects in the memory segment.
  562. //!Can throw boost::interprocess::bad_alloc if there is no enough memory.
  563. void reserve_unique_objects(size_type num)
  564. { mp_header->reserve_unique_objects(num); }
  565. //!Calls shrink_to_fit in both named and unique object indexes
  566. //to try to free unused memory from those indexes.
  567. void shrink_to_fit_indexes()
  568. { mp_header->shrink_to_fit_indexes(); }
  569. //!Returns the number of named objects stored
  570. //!in the managed segment.
  571. size_type get_num_named_objects()
  572. { return mp_header->get_num_named_objects(); }
  573. //!Returns the number of unique objects stored
  574. //!in the managed segment.
  575. size_type get_num_unique_objects()
  576. { return mp_header->get_num_unique_objects(); }
  577. //!Returns a constant iterator to the index storing the
  578. //!named allocations. NOT thread-safe. Never throws.
  579. const_named_iterator named_begin() const
  580. { return mp_header->named_begin(); }
  581. //!Returns a constant iterator to the end of the index
  582. //!storing the named allocations. NOT thread-safe. Never throws.
  583. const_named_iterator named_end() const
  584. { return mp_header->named_end(); }
  585. //!Returns a constant iterator to the index storing the
  586. //!unique allocations. NOT thread-safe. Never throws.
  587. const_unique_iterator unique_begin() const
  588. { return mp_header->unique_begin(); }
  589. //!Returns a constant iterator to the end of the index
  590. //!storing the unique allocations. NOT thread-safe. Never throws.
  591. const_unique_iterator unique_end() const
  592. { return mp_header->unique_end(); }
  593. //!This is the default allocator to allocate types T
  594. //!from this managed segment
  595. template<class T>
  596. struct allocator
  597. {
  598. typedef typename segment_manager::template allocator<T>::type type;
  599. };
  600. //!Returns an instance of the default allocator for type T
  601. //!initialized that allocates memory from this segment manager.
  602. template<class T>
  603. typename allocator<T>::type
  604. get_allocator()
  605. { return mp_header->template get_allocator<T>(); }
  606. //!This is the default deleter to delete types T
  607. //!from this managed segment.
  608. template<class T>
  609. struct deleter
  610. {
  611. typedef typename segment_manager::template deleter<T>::type type;
  612. };
  613. //!Returns an instance of the default allocator for type T
  614. //!initialized that allocates memory from this segment manager.
  615. template<class T>
  616. typename deleter<T>::type
  617. get_deleter()
  618. { return mp_header->template get_deleter<T>(); }
  619. #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
  620. //!Tries to find a previous named allocation address. Returns a memory
  621. //!buffer and the object count. If not found returned pointer is 0.
  622. //!Never throws.
  623. template <class T>
  624. std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name)
  625. { return mp_header->template find_no_lock<T>(name); }
  626. #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
  627. protected:
  628. //!Swaps the segment manager's managed by this managed memory segment.
  629. //!NOT thread-safe. Never throws.
  630. void swap(basic_managed_memory_impl &other)
  631. { (simple_swap)(mp_header, other.mp_header); }
  632. private:
  633. segment_manager *mp_header;
  634. };
  635. template<class BasicManagedMemoryImpl>
  636. class create_open_func
  637. {
  638. typedef typename BasicManagedMemoryImpl::size_type size_type;
  639. public:
  640. create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type)
  641. : m_frontend(frontend), m_type(type){}
  642. bool operator()(void *addr, std::size_t size, bool created) const
  643. {
  644. if( ((m_type == DoOpen) && created) ||
  645. ((m_type == DoCreate) && !created) ||
  646. //Check for overflow
  647. size_type(-1) < size ){
  648. return false;
  649. }
  650. else if(created){
  651. return m_frontend->create_impl(addr, static_cast<size_type>(size));
  652. }
  653. else{
  654. return m_frontend->open_impl (addr, static_cast<size_type>(size));
  655. }
  656. }
  657. static std::size_t get_min_size()
  658. {
  659. const size_type sz = BasicManagedMemoryImpl::segment_manager::get_min_size();
  660. if(sz > std::size_t(-1)){
  661. //The minimum size is not representable by std::size_t
  662. BOOST_ASSERT(false);
  663. return std::size_t(-1);
  664. }
  665. else{
  666. return static_cast<std::size_t>(sz);
  667. }
  668. }
  669. private:
  670. BasicManagedMemoryImpl *m_frontend;
  671. create_enum_t m_type;
  672. };
  673. } //namespace ipcdetail {
  674. } //namespace interprocess {
  675. } //namespace boost {
  676. #include <boost/interprocess/detail/config_end.hpp>
  677. #endif //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP