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 + -
显示快捷键?