managed_memory_impl.hpp 29 KB

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