////////////////////////////////////////////////////////////////////////////// | |
// | |
// (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 detail { | |
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 std::ptrdiff_t 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 std::size_t 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, std::size_t 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; | |
std::size_t 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, std::size_t 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, std::size_t) | |
{ | |
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(std::size_t 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. | |
std::size_t get_size () const | |
{ return mp_header->get_size() + Offset; } | |
//!Returns the number of free bytes of the memory | |
//!segment | |
std::size_t 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 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 (std::size_t 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 (std::size_t 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 (std::size_t nbytes, std::size_t 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, std::size_t limit_size, | |
std::size_t preferred_size,std::size_t &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(std::size_t nbytes, std::size_t alignment) | |
{ return mp_header->allocate_aligned(nbytes, alignment); } | |
/// @cond | |
//Experimental. Don't use. | |
//!Allocates n_elements of elem_size bytes. | |
multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t 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 std::size_t *elem_sizes, std::size_t n_elements) | |
{ return mp_header->allocate_many(elem_sizes, n_elements); } | |
//!Allocates n_elements of elem_size bytes. | |
multiallocation_chain allocate_many(std::size_t elem_bytes, std::size_t 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 std::size_t *elem_sizes, std::size_t 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*, std::size_t> 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 detail::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 std::size_t 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(std::size_t 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(std::size_t 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. | |
std::size_t get_num_named_objects() | |
{ return mp_header->get_num_named_objects(); } | |
//!Returns the number of unique objects stored | |
//!in the managed segment. | |
std::size_t 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*, std::size_t> 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, detail::create_enum_t type) | |
: m_frontend(frontend), m_type(type){} | |
bool operator()(void *addr, std::size_t size, bool created) const | |
{ | |
if(((m_type == detail::DoOpen) && created) || | |
((m_type == detail::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; | |
detail::create_enum_t m_type; | |
}; | |
} //namespace detail { | |
} //namespace interprocess { | |
} //namespace boost { | |
#include <boost/interprocess/detail/config_end.hpp> | |
#endif //BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP | |