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