You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
754 lines
28 KiB
754 lines
28 KiB
////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// (C) Copyright Ion Gaztanaga 2005-2009. Distributed under the Boost |
|
// Software License, Version 1.0. (See accompanying file |
|
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
|
// |
|
// See http://www.boost.org/libs/interprocess for documentation. |
|
// |
|
////////////////////////////////////////////////////////////////////////////// |
|
|
|
#ifndef BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP |
|
#define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP |
|
|
|
#if (defined _MSC_VER) && (_MSC_VER >= 1200) |
|
# pragma once |
|
#endif |
|
|
|
#include <boost/interprocess/detail/config_begin.hpp> |
|
#include <boost/interprocess/detail/workaround.hpp> |
|
|
|
#include <boost/interprocess/interprocess_fwd.hpp> |
|
#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp> |
|
#include <boost/interprocess/sync/mutex_family.hpp> |
|
#include <boost/interprocess/detail/utilities.hpp> |
|
#include <boost/interprocess/detail/os_file_functions.hpp> |
|
#include <boost/interprocess/creation_tags.hpp> |
|
#include <boost/interprocess/sync/interprocess_mutex.hpp> |
|
#include <boost/interprocess/exceptions.hpp> |
|
#include <boost/interprocess/offset_ptr.hpp> |
|
#include <boost/interprocess/segment_manager.hpp> |
|
#include <boost/interprocess/sync/scoped_lock.hpp> |
|
// |
|
#include <boost/detail/no_exceptions_support.hpp> |
|
// |
|
#include <utility> |
|
#include <fstream> |
|
#include <new> |
|
#include <boost/assert.hpp> |
|
|
|
//!\file |
|
//!Describes a named shared memory allocation user class. |
|
//! |
|
|
|
namespace boost { |
|
namespace interprocess { |
|
namespace ipcdetail { |
|
|
|
template<class BasicManagedMemoryImpl> |
|
class create_open_func; |
|
|
|
template< |
|
class CharType, |
|
class MemoryAlgorithm, |
|
template<class IndexConfig> class IndexType |
|
> |
|
struct segment_manager_type |
|
{ |
|
typedef segment_manager<CharType, MemoryAlgorithm, IndexType> type; |
|
}; |
|
|
|
//!This class is designed to be a base class to classes that manage |
|
//!creation of objects in a fixed size memory buffer. Apart |
|
//!from allocating raw memory, the user can construct named objects. To |
|
//!achieve this, this class uses the reserved space provided by the allocation |
|
//!algorithm to place a named_allocator_algo, who takes care of name mappings. |
|
//!The class can be customized with the char type used for object names |
|
//!and the memory allocation algorithm to be used.*/ |
|
template < class CharType |
|
, class MemoryAlgorithm |
|
, template<class IndexConfig> class IndexType |
|
, std::size_t Offset = 0 |
|
> |
|
class basic_managed_memory_impl |
|
{ |
|
//Non-copyable |
|
basic_managed_memory_impl(const basic_managed_memory_impl &); |
|
basic_managed_memory_impl &operator=(const basic_managed_memory_impl &); |
|
|
|
template<class BasicManagedMemoryImpl> |
|
friend class create_open_func; |
|
|
|
public: |
|
typedef typename segment_manager_type |
|
<CharType, MemoryAlgorithm, IndexType>::type segment_manager; |
|
typedef CharType char_type; |
|
typedef MemoryAlgorithm memory_algorithm; |
|
typedef typename MemoryAlgorithm::mutex_family mutex_family; |
|
typedef CharType char_t; |
|
typedef typename MemoryAlgorithm::size_type size_type; |
|
typedef typename MemoryAlgorithm::difference_type difference_type; |
|
typedef difference_type handle_t; |
|
typedef typename segment_manager:: |
|
const_named_iterator const_named_iterator; |
|
typedef typename segment_manager:: |
|
const_unique_iterator const_unique_iterator; |
|
|
|
/// @cond |
|
|
|
typedef typename |
|
segment_manager::char_ptr_holder_t char_ptr_holder_t; |
|
//Experimental. Don't use. |
|
|
|
typedef typename segment_manager::multiallocation_chain multiallocation_chain; |
|
|
|
/// @endcond |
|
|
|
static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation; |
|
|
|
private: |
|
typedef basic_managed_memory_impl |
|
<CharType, MemoryAlgorithm, IndexType, Offset> self_t; |
|
protected: |
|
template<class ManagedMemory> |
|
static bool grow(const char *filename, size_type extra_bytes) |
|
{ |
|
typedef typename ManagedMemory::device_type device_type; |
|
//Increase file size |
|
try{ |
|
offset_t old_size; |
|
{ |
|
device_type f(open_or_create, filename, read_write); |
|
if(!f.get_size(old_size)) |
|
return false; |
|
f.truncate(old_size + extra_bytes); |
|
} |
|
ManagedMemory managed_memory(open_only, filename); |
|
//Grow always works |
|
managed_memory.self_t::grow(extra_bytes); |
|
} |
|
catch(...){ |
|
return false; |
|
} |
|
return true; |
|
} |
|
|
|
template<class ManagedMemory> |
|
static bool shrink_to_fit(const char *filename) |
|
{ |
|
typedef typename ManagedMemory::device_type device_type; |
|
size_type new_size, old_size; |
|
try{ |
|
ManagedMemory managed_memory(open_only, filename); |
|
old_size = managed_memory.get_size(); |
|
managed_memory.self_t::shrink_to_fit(); |
|
new_size = managed_memory.get_size(); |
|
} |
|
catch(...){ |
|
return false; |
|
} |
|
|
|
//Decrease file size |
|
{ |
|
device_type f(open_or_create, filename, read_write); |
|
f.truncate(new_size); |
|
} |
|
return true; |
|
} |
|
|
|
//!Constructor. Allocates basic resources. Never throws. |
|
basic_managed_memory_impl() |
|
: mp_header(0){} |
|
|
|
//!Destructor. Calls close. Never throws. |
|
~basic_managed_memory_impl() |
|
{ this->close_impl(); } |
|
|
|
//!Places segment manager in the reserved space. This can throw. |
|
bool create_impl (void *addr, size_type size) |
|
{ |
|
if(mp_header) return false; |
|
|
|
//Check if there is enough space |
|
if(size < segment_manager::get_min_size()) |
|
return false; |
|
|
|
//This function should not throw. The index construction can |
|
//throw if constructor allocates memory. So we must catch it. |
|
BOOST_TRY{ |
|
//Let's construct the allocator in memory |
|
mp_header = new(addr) segment_manager(size); |
|
} |
|
BOOST_CATCH(...){ |
|
return false; |
|
} |
|
BOOST_CATCH_END |
|
return true; |
|
} |
|
|
|
//!Connects to a segment manager in the reserved buffer. Never throws. |
|
bool open_impl (void *addr, size_type) |
|
{ |
|
if(mp_header) return false; |
|
mp_header = static_cast<segment_manager*>(addr); |
|
return true; |
|
} |
|
|
|
//!Frees resources. Never throws. |
|
bool close_impl() |
|
{ |
|
bool ret = mp_header != 0; |
|
mp_header = 0; |
|
return ret; |
|
} |
|
|
|
//!Frees resources and destroys common resources. Never throws. |
|
bool destroy_impl() |
|
{ |
|
if(mp_header == 0) |
|
return false; |
|
mp_header->~segment_manager(); |
|
this->close_impl(); |
|
return true; |
|
} |
|
|
|
//! |
|
void grow(size_type extra_bytes) |
|
{ mp_header->grow(extra_bytes); } |
|
|
|
void shrink_to_fit() |
|
{ mp_header->shrink_to_fit(); } |
|
|
|
public: |
|
|
|
//!Returns segment manager. Never throws. |
|
segment_manager *get_segment_manager() const |
|
{ return mp_header; } |
|
|
|
//!Returns the base address of the memory in this process. Never throws. |
|
void * get_address () const |
|
{ return reinterpret_cast<char*>(mp_header) - Offset; } |
|
|
|
//!Returns the size of memory segment. Never throws. |
|
size_type get_size () const |
|
{ return mp_header->get_size() + Offset; } |
|
|
|
//!Returns the number of free bytes of the memory |
|
//!segment |
|
size_type get_free_memory() const |
|
{ return mp_header->get_free_memory(); } |
|
|
|
//!Returns the result of "all_memory_deallocated()" function |
|
//!of the used memory algorithm |
|
bool all_memory_deallocated() |
|
{ return mp_header->all_memory_deallocated(); } |
|
|
|
//!Returns the result of "check_sanity()" function |
|
//!of the used memory algorithm |
|
bool check_sanity() |
|
{ return mp_header->check_sanity(); } |
|
|
|
//!Writes to zero free memory (memory not yet allocated) of |
|
//!the memory algorithm |
|
void zero_free_memory() |
|
{ mp_header->zero_free_memory(); } |
|
|
|
//!Transforms an absolute address into an offset from base address. |
|
//!The address must belong to the memory segment. Never throws. |
|
handle_t get_handle_from_address (const void *ptr) const |
|
{ |
|
return (handle_t)(reinterpret_cast<const char*>(ptr) - |
|
reinterpret_cast<const char*>(this->get_address())); |
|
} |
|
|
|
//!Returns true if the address belongs to the managed memory segment |
|
bool belongs_to_segment (const void *ptr) const |
|
{ |
|
return ptr >= this->get_address() && |
|
ptr < (reinterpret_cast<const char*>(this->get_address()) + this->get_size()); |
|
} |
|
|
|
//!Transforms previously obtained offset into an absolute address in the |
|
//!process space of the current process. Never throws.*/ |
|
void * get_address_from_handle (handle_t offset) const |
|
{ return reinterpret_cast<char*>(this->get_address()) + offset; } |
|
|
|
//!Searches for nbytes of free memory in the segment, marks the |
|
//!memory as used and return the pointer to the memory. If no |
|
//!memory is available throws a boost::interprocess::bad_alloc exception |
|
void* allocate (size_type nbytes) |
|
{ return mp_header->allocate(nbytes); } |
|
|
|
//!Searches for nbytes of free memory in the segment, marks the |
|
//!memory as used and return the pointer to the memory. If no memory |
|
//!is available returns 0. Never throws. |
|
void* allocate (size_type nbytes, std::nothrow_t nothrow) |
|
{ return mp_header->allocate(nbytes, nothrow); } |
|
|
|
//!Allocates nbytes bytes aligned to "alignment" bytes. "alignment" |
|
//!must be power of two. If no memory |
|
//!is available returns 0. Never throws. |
|
void * allocate_aligned (size_type nbytes, size_type alignment, std::nothrow_t nothrow) |
|
{ return mp_header->allocate_aligned(nbytes, alignment, nothrow); } |
|
|
|
template<class T> |
|
std::pair<T *, bool> |
|
allocation_command (boost::interprocess::allocation_type command, size_type limit_size, |
|
size_type preferred_size,size_type &received_size, |
|
T *reuse_ptr = 0) |
|
{ |
|
return mp_header->allocation_command |
|
(command, limit_size, preferred_size, received_size, reuse_ptr); |
|
} |
|
|
|
//!Allocates nbytes bytes aligned to "alignment" bytes. "alignment" |
|
//!must be power of two. If no |
|
//!memory is available throws a boost::interprocess::bad_alloc exception |
|
void * allocate_aligned(size_type nbytes, size_type alignment) |
|
{ return mp_header->allocate_aligned(nbytes, alignment); } |
|
|
|
/// @cond |
|
|
|
//Experimental. Don't use. |
|
|
|
//!Allocates n_elements of elem_size bytes. |
|
multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements) |
|
{ return mp_header->allocate_many(elem_bytes, num_elements); } |
|
|
|
//!Allocates n_elements, each one of elem_sizes[i] bytes. |
|
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements) |
|
{ return mp_header->allocate_many(elem_sizes, n_elements); } |
|
|
|
//!Allocates n_elements of elem_size bytes. |
|
multiallocation_chain allocate_many(size_type elem_bytes, size_type num_elements, std::nothrow_t nothrow) |
|
{ return mp_header->allocate_many(elem_bytes, num_elements, nothrow); } |
|
|
|
//!Allocates n_elements, each one of elem_sizes[i] bytes. |
|
multiallocation_chain allocate_many(const size_type *elem_sizes, size_type n_elements, std::nothrow_t nothrow) |
|
{ return mp_header->allocate_many(elem_sizes, n_elements, nothrow); } |
|
|
|
//!Allocates n_elements, each one of elem_sizes[i] bytes. |
|
void deallocate_many(multiallocation_chain chain) |
|
{ return mp_header->deallocate_many(boost::interprocess::move(chain)); } |
|
|
|
/// @endcond |
|
|
|
//!Marks previously allocated memory as free. Never throws. |
|
void deallocate (void *addr) |
|
{ if (mp_header) mp_header->deallocate(addr); } |
|
|
|
//!Tries to find a previous named allocation address. Returns a memory |
|
//!buffer and the object count. If not found returned pointer is 0. |
|
//!Never throws. |
|
template <class T> |
|
std::pair<T*, size_type> find (char_ptr_holder_t name) |
|
{ return mp_header->template find<T>(name); } |
|
|
|
//!Creates a named object or array in memory |
|
//! |
|
//!Allocates and constructs a T object or an array of T in memory, |
|
//!associates this with the given name and returns a pointer to the |
|
//!created object. If an array is being constructed all objects are |
|
//!created using the same parameters given to this function. |
|
//! |
|
//!-> If the name was previously used, returns 0. |
|
//! |
|
//!-> Throws boost::interprocess::bad_alloc if there is no available memory |
|
//! |
|
//!-> If T's constructor throws, the function throws that exception. |
|
//! |
|
//!Memory is freed automatically if T's constructor throws and if an |
|
//!array was being constructed, destructors of created objects are called |
|
//!before freeing the memory. |
|
template <class T> |
|
typename segment_manager::template construct_proxy<T>::type |
|
construct(char_ptr_holder_t name) |
|
{ return mp_header->template construct<T>(name); } |
|
|
|
//!Finds or creates a named object or array in memory |
|
//! |
|
//!Tries to find an object with the given name in memory. If |
|
//!found, returns the pointer to this pointer. If the object is not found, |
|
//!allocates and constructs a T object or an array of T in memory, |
|
//!associates this with the given name and returns a pointer to the |
|
//!created object. If an array is being constructed all objects are |
|
//!created using the same parameters given to this function. |
|
//! |
|
//!-> Throws boost::interprocess::bad_alloc if there is no available memory |
|
//! |
|
//!-> If T's constructor throws, the function throws that exception. |
|
//! |
|
//!Memory is freed automatically if T's constructor throws and if an |
|
//!array was being constructed, destructors of created objects are called |
|
//!before freeing the memory. |
|
template <class T> |
|
typename segment_manager::template construct_proxy<T>::type |
|
find_or_construct(char_ptr_holder_t name) |
|
{ return mp_header->template find_or_construct<T>(name); } |
|
|
|
//!Creates a named object or array in memory |
|
//! |
|
//!Allocates and constructs a T object or an array of T in memory, |
|
//!associates this with the given name and returns a pointer to the |
|
//!created object. If an array is being constructed all objects are |
|
//!created using the same parameters given to this function. |
|
//! |
|
//!-> If the name was previously used, returns 0. |
|
//! |
|
//!-> Returns 0 if there is no available memory |
|
//! |
|
//!-> If T's constructor throws, the function throws that exception. |
|
//! |
|
//!Memory is freed automatically if T's constructor throws and if an |
|
//!array was being constructed, destructors of created objects are called |
|
//!before freeing the memory. |
|
template <class T> |
|
typename segment_manager::template construct_proxy<T>::type |
|
construct(char_ptr_holder_t name, std::nothrow_t nothrow) |
|
{ return mp_header->template construct<T>(name, nothrow); } |
|
|
|
//!Finds or creates a named object or array in memory |
|
//! |
|
//!Tries to find an object with the given name in memory. If |
|
//!found, returns the pointer to this pointer. If the object is not found, |
|
//!allocates and constructs a T object or an array of T in memory, |
|
//!associates this with the given name and returns a pointer to the |
|
//!created object. If an array is being constructed all objects are |
|
//!created using the same parameters given to this function. |
|
//! |
|
//!-> Returns 0 if there is no available memory |
|
//! |
|
//!-> If T's constructor throws, the function throws that exception. |
|
//! |
|
//!Memory is freed automatically if T's constructor throws and if an |
|
//!array was being constructed, destructors of created objects are called |
|
//!before freeing the memory. |
|
template <class T> |
|
typename segment_manager::template construct_proxy<T>::type |
|
find_or_construct(char_ptr_holder_t name, std::nothrow_t nothrow) |
|
{ return mp_header->template find_or_construct<T>(name, nothrow); } |
|
|
|
//!Creates a named array from iterators in memory |
|
//! |
|
//!Allocates and constructs an array of T in memory, |
|
//!associates this with the given name and returns a pointer to the |
|
//!created object. Each element in the array is created using the |
|
//!objects returned when dereferencing iterators as parameters |
|
//!and incrementing all iterators for each element. |
|
//! |
|
//!-> If the name was previously used, returns 0. |
|
//! |
|
//!-> Throws boost::interprocess::bad_alloc if there is no available memory |
|
//! |
|
//!-> If T's constructor throws, the function throws that exception. |
|
//! |
|
//!Memory is freed automatically if T's constructor throws and |
|
//!destructors of created objects are called before freeing the memory. |
|
template <class T> |
|
typename segment_manager::template construct_iter_proxy<T>::type |
|
construct_it(char_ptr_holder_t name) |
|
{ return mp_header->template construct_it<T>(name); } |
|
|
|
//!Finds or creates a named array from iterators in memory |
|
//! |
|
//!Tries to find an object with the given name in memory. If |
|
//!found, returns the pointer to this pointer. If the object is not found, |
|
//!allocates and constructs an array of T in memory, |
|
//!associates this with the given name and returns a pointer to the |
|
//!created object. Each element in the array is created using the |
|
//!objects returned when dereferencing iterators as parameters |
|
//!and incrementing all iterators for each element. |
|
//! |
|
//!-> If the name was previously used, returns 0. |
|
//! |
|
//!-> Throws boost::interprocess::bad_alloc if there is no available memory |
|
//! |
|
//!-> If T's constructor throws, the function throws that exception. |
|
//! |
|
//!Memory is freed automatically if T's constructor throws and |
|
//!destructors of created objects are called before freeing the memory. |
|
template <class T> |
|
typename segment_manager::template construct_iter_proxy<T>::type |
|
find_or_construct_it(char_ptr_holder_t name) |
|
{ return mp_header->template find_or_construct_it<T>(name); } |
|
|
|
//!Creates a named array from iterators in memory |
|
//! |
|
//!Allocates and constructs an array of T in memory, |
|
//!associates this with the given name and returns a pointer to the |
|
//!created object. Each element in the array is created using the |
|
//!objects returned when dereferencing iterators as parameters |
|
//!and incrementing all iterators for each element. |
|
//! |
|
//!-> If the name was previously used, returns 0. |
|
//! |
|
//!-> If there is no available memory, returns 0. |
|
//! |
|
//!-> If T's constructor throws, the function throws that exception. |
|
//! |
|
//!Memory is freed automatically if T's constructor throws and |
|
//!destructors of created objects are called before freeing the memory.*/ |
|
template <class T> |
|
typename segment_manager::template construct_iter_proxy<T>::type |
|
construct_it(char_ptr_holder_t name, std::nothrow_t nothrow) |
|
{ return mp_header->template construct_it<T>(name, nothrow); } |
|
|
|
//!Finds or creates a named array from iterators in memory |
|
//! |
|
//!Tries to find an object with the given name in memory. If |
|
//!found, returns the pointer to this pointer. If the object is not found, |
|
//!allocates and constructs an array of T in memory, |
|
//!associates this with the given name and returns a pointer to the |
|
//!created object. Each element in the array is created using the |
|
//!objects returned when dereferencing iterators as parameters |
|
//!and incrementing all iterators for each element. |
|
//! |
|
//!-> If the name was previously used, returns 0. |
|
//! |
|
//!-> If there is no available memory, returns 0. |
|
//! |
|
//!-> If T's constructor throws, the function throws that exception. |
|
//! |
|
//!Memory is freed automatically if T's constructor throws and |
|
//!destructors of created objects are called before freeing the memory.*/ |
|
template <class T> |
|
typename segment_manager::template construct_iter_proxy<T>::type |
|
find_or_construct_it(char_ptr_holder_t name, std::nothrow_t nothrow) |
|
{ return mp_header->template find_or_construct_it<T>(name, nothrow); } |
|
|
|
//!Calls a functor and guarantees that no new construction, search or |
|
//!destruction will be executed by any process while executing the object |
|
//!function call. If the functor throws, this function throws. |
|
template <class Func> |
|
void atomic_func(Func &f) |
|
{ mp_header->atomic_func(f); } |
|
|
|
//!Tries to call a functor guaranteeing that no new construction, search or |
|
//!destruction will be executed by any process while executing the object |
|
//!function call. If the atomic function can't be immediatelly executed |
|
//!because the internal mutex is already locked, returns false. |
|
//!If the functor throws, this function throws. |
|
template <class Func> |
|
bool try_atomic_func(Func &f) |
|
{ return mp_header->try_atomic_func(f); } |
|
|
|
//!Destroys a named memory object or array. |
|
//! |
|
//!Finds the object with the given name, calls its destructors, |
|
//!frees used memory and returns true. |
|
//! |
|
//!-> If the object is not found, it returns false. |
|
//! |
|
//!Exception Handling: |
|
//! |
|
//!When deleting a dynamically object or array, the Standard |
|
//!does not guarantee that dynamically allocated memory, will be released. |
|
//!Also, when deleting arrays, the Standard doesn't require calling |
|
//!destructors for the rest of the objects if for one of them the destructor |
|
//!terminated with an exception. |
|
//! |
|
//!Destroying an object: |
|
//! |
|
//!If the destructor throws, the memory will be freed and that exception |
|
//!will be thrown. |
|
//! |
|
//!Destroying an array: |
|
//! |
|
//!When destroying an array, if a destructor throws, the rest of |
|
//!destructors are called. If any of these throws, the exceptions are |
|
//!ignored. The name association will be erased, memory will be freed and |
|
//!the first exception will be thrown. This guarantees the unlocking of |
|
//!mutexes and other resources. |
|
//! |
|
//!For all theses reasons, classes with throwing destructors are not |
|
//!recommended. |
|
template <class T> |
|
bool destroy(const CharType *name) |
|
{ return mp_header->template destroy<T>(name); } |
|
|
|
//!Destroys the unique instance of type T |
|
//! |
|
//!Calls the destructor, frees used memory and returns true. |
|
//! |
|
//!Exception Handling: |
|
//! |
|
//!When deleting a dynamically object, the Standard does not |
|
//!guarantee that dynamically allocated memory will be released. |
|
//! |
|
//!Destroying an object: |
|
//! |
|
//!If the destructor throws, the memory will be freed and that exception |
|
//!will be thrown. |
|
//! |
|
//!For all theses reasons, classes with throwing destructors are not |
|
//!recommended for memory. |
|
template <class T> |
|
bool destroy(const ipcdetail::unique_instance_t *const ) |
|
{ return mp_header->template destroy<T>(unique_instance); } |
|
|
|
//!Destroys the object (named, unique, or anonymous) |
|
//! |
|
//!Calls the destructor, frees used memory and returns true. |
|
//! |
|
//!Exception Handling: |
|
//! |
|
//!When deleting a dynamically object, the Standard does not |
|
//!guarantee that dynamically allocated memory will be released. |
|
//! |
|
//!Destroying an object: |
|
//! |
|
//!If the destructor throws, the memory will be freed and that exception |
|
//!will be thrown. |
|
//! |
|
//!For all theses reasons, classes with throwing destructors are not |
|
//!recommended for memory. |
|
template <class T> |
|
void destroy_ptr(const T *ptr) |
|
{ mp_header->template destroy_ptr<T>(ptr); } |
|
|
|
//!Returns the name of an object created with construct/find_or_construct |
|
//!functions. Does not throw |
|
template<class T> |
|
static const char_type *get_instance_name(const T *ptr) |
|
{ return segment_manager::get_instance_name(ptr); } |
|
|
|
//!Returns is the type an object created with construct/find_or_construct |
|
//!functions. Does not throw. |
|
template<class T> |
|
static instance_type get_instance_type(const T *ptr) |
|
{ return segment_manager::get_instance_type(ptr); } |
|
|
|
//!Returns the length of an object created with construct/find_or_construct |
|
//!functions (1 if is a single element, >=1 if it's an array). Does not throw. |
|
template<class T> |
|
static size_type get_instance_length(const T *ptr) |
|
{ return segment_manager::get_instance_length(ptr); } |
|
|
|
//!Preallocates needed index resources to optimize the |
|
//!creation of "num" named objects in the memory segment. |
|
//!Can throw boost::interprocess::bad_alloc if there is no enough memory. |
|
void reserve_named_objects(size_type num) |
|
{ mp_header->reserve_named_objects(num); } |
|
|
|
//!Preallocates needed index resources to optimize the |
|
//!creation of "num" unique objects in the memory segment. |
|
//!Can throw boost::interprocess::bad_alloc if there is no enough memory. |
|
void reserve_unique_objects(size_type num) |
|
{ mp_header->reserve_unique_objects(num); } |
|
|
|
//!Calls shrink_to_fit in both named and unique object indexes |
|
//to try to free unused memory from those indexes. |
|
void shrink_to_fit_indexes() |
|
{ mp_header->shrink_to_fit_indexes(); } |
|
|
|
//!Returns the number of named objects stored |
|
//!in the managed segment. |
|
size_type get_num_named_objects() |
|
{ return mp_header->get_num_named_objects(); } |
|
|
|
//!Returns the number of unique objects stored |
|
//!in the managed segment. |
|
size_type get_num_unique_objects() |
|
{ return mp_header->get_num_unique_objects(); } |
|
|
|
//!Returns a constant iterator to the index storing the |
|
//!named allocations. NOT thread-safe. Never throws. |
|
const_named_iterator named_begin() const |
|
{ return mp_header->named_begin(); } |
|
|
|
//!Returns a constant iterator to the end of the index |
|
//!storing the named allocations. NOT thread-safe. Never throws. |
|
const_named_iterator named_end() const |
|
{ return mp_header->named_end(); } |
|
|
|
//!Returns a constant iterator to the index storing the |
|
//!unique allocations. NOT thread-safe. Never throws. |
|
const_unique_iterator unique_begin() const |
|
{ return mp_header->unique_begin(); } |
|
|
|
//!Returns a constant iterator to the end of the index |
|
//!storing the unique allocations. NOT thread-safe. Never throws. |
|
const_unique_iterator unique_end() const |
|
{ return mp_header->unique_end(); } |
|
|
|
//!This is the default allocator to allocate types T |
|
//!from this managed segment |
|
template<class T> |
|
struct allocator |
|
{ |
|
typedef typename segment_manager::template allocator<T>::type type; |
|
}; |
|
|
|
//!Returns an instance of the default allocator for type T |
|
//!initialized that allocates memory from this segment manager. |
|
template<class T> |
|
typename allocator<T>::type |
|
get_allocator() |
|
{ return mp_header->template get_allocator<T>(); } |
|
|
|
//!This is the default deleter to delete types T |
|
//!from this managed segment. |
|
template<class T> |
|
struct deleter |
|
{ |
|
typedef typename segment_manager::template deleter<T>::type type; |
|
}; |
|
|
|
//!Returns an instance of the default allocator for type T |
|
//!initialized that allocates memory from this segment manager. |
|
template<class T> |
|
typename deleter<T>::type |
|
get_deleter() |
|
{ return mp_header->template get_deleter<T>(); } |
|
|
|
/// @cond |
|
//!Tries to find a previous named allocation address. Returns a memory |
|
//!buffer and the object count. If not found returned pointer is 0. |
|
//!Never throws. |
|
template <class T> |
|
std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name) |
|
{ return mp_header->template find_no_lock<T>(name); } |
|
/// @endcond |
|
|
|
protected: |
|
//!Swaps the segment manager's managed by this managed memory segment. |
|
//!NOT thread-safe. Never throws. |
|
void swap(basic_managed_memory_impl &other) |
|
{ std::swap(mp_header, other.mp_header); } |
|
|
|
private: |
|
segment_manager *mp_header; |
|
}; |
|
|
|
template<class BasicManagedMemoryImpl> |
|
class create_open_func |
|
{ |
|
public: |
|
create_open_func(BasicManagedMemoryImpl * const frontend, ipcdetail::create_enum_t type) |
|
: m_frontend(frontend), m_type(type){} |
|
|
|
bool operator()(void *addr, typename BasicManagedMemoryImpl::size_type size, bool created) const |
|
{ |
|
if(((m_type == ipcdetail::DoOpen) && created) || |
|
((m_type == ipcdetail::DoCreate) && !created)) |
|
return false; |
|
|
|
if(created) |
|
return m_frontend->create_impl(addr, size); |
|
else |
|
return m_frontend->open_impl (addr, size); |
|
} |
|
|
|
private: |
|
BasicManagedMemoryImpl *m_frontend; |
|
ipcdetail::create_enum_t m_type; |
|
}; |
|
|
|
} //namespace ipcdetail { |
|
} //namespace interprocess { |
|
} //namespace boost { |
|
|
|
#include <boost/interprocess/detail/config_end.hpp> |
|
|
|
#endif //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP |
|
|
|
|