managed_memory_impl.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 740 行 · 第 1/2 页
HPP
740 行
////////////////////////////////////////////////////////////////////////////////// (C) Copyright Ion Gaztanaga 2005-2008. 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 <cassert>//!\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_iterator multiallocation_iterator; /// @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*>(ptr) + 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 (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_iterator 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_iterator 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_iterator 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_iterator 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); } /// @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. //!
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?