intersegment_ptr.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,042 行 · 第 1/3 页

HPP
1,042
字号
////////////////////////////////////////////////////////////////////////////////// (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_INTERSEGMENT_PTR_HPP#define BOOST_INTERPROCESS_INTERSEGMENT_PTR_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/detail/utilities.hpp>#include <boost/interprocess/detail/math_functions.hpp>#include <boost/interprocess/detail/cast_tags.hpp>#include <boost/assert.hpp>#include <boost/interprocess/sync/scoped_lock.hpp>#include <boost/interprocess/sync/interprocess_mutex.hpp>#include <boost/interprocess/containers/flat_map.hpp>#include <boost/interprocess/containers/vector.hpp>   //vector#include <boost/interprocess/containers/set.hpp>      //set#include <boost/detail/no_exceptions_support.hpp>#include <boost/interprocess/detail/mpl.hpp>#include <climits>#include <iterator>#include <boost/static_assert.hpp>  //BOOST_STATIC_ASSERT#include <climits>   //CHAR_BIT#include <boost/integer/static_log2.hpp>#include <cassert>   //assert#include <boost/interprocess/detail/multi_segment_services.hpp>//!\file//!namespace boost {//Predeclarationstemplate <class T>struct has_trivial_constructor;template <class T>struct has_trivial_destructor;namespace interprocess {template <class T>struct is_multisegment_ptr;struct intersegment_base{   typedef intersegment_base  self_t;   BOOST_STATIC_ASSERT((sizeof(std::size_t) == sizeof(void*)));   BOOST_STATIC_ASSERT((sizeof(void*)*CHAR_BIT == 32 || sizeof(void*)*CHAR_BIT == 64));   static const std::size_t size_t_bits = (sizeof(void*)*CHAR_BIT == 32) ? 32 : 64;   static const std::size_t ctrl_bits = 2;   static const std::size_t align_bits = 12;   static const std::size_t align      = std::size_t(1) << align_bits;   static const std::size_t max_segment_size_bits = size_t_bits - 2;   static const std::size_t max_segment_size = std::size_t(1) << max_segment_size_bits;   static const std::size_t begin_bits             = max_segment_size_bits - align_bits;   static const std::size_t pow_size_bits_helper = static_log2<max_segment_size_bits>::value;   static const std::size_t pow_size_bits =       (max_segment_size_bits == (std::size_t(1) << pow_size_bits_helper)) ?       pow_size_bits_helper : pow_size_bits_helper + 1;   static const std::size_t frc_size_bits =      size_t_bits - ctrl_bits - begin_bits - pow_size_bits;   BOOST_STATIC_ASSERT(((size_t_bits - pow_size_bits - frc_size_bits) >= ctrl_bits ));   static const std::size_t relative_size_bits =      size_t_bits - max_segment_size_bits - ctrl_bits;   static const std::size_t is_pointee_outside  = 0;   static const std::size_t is_in_stack         = 1;   static const std::size_t is_relative         = 2;   static const std::size_t is_segmented        = 3;   static const std::size_t is_max_mode         = 4;   intersegment_base()   {      this->set_mode(is_pointee_outside);      this->set_null();   }   struct relative_addressing   {      std::size_t ctrl     :  2;      std::size_t pow      :  pow_size_bits;      std::size_t frc      :  frc_size_bits;      std::size_t beg      :  begin_bits;      std::ptrdiff_t off   :  sizeof(ptrdiff_t)*CHAR_BIT - 2;      std::ptrdiff_t bits  :  2;   };   struct direct_addressing   {      std::size_t ctrl     :  2;      std::size_t dummy    :  sizeof(std::size_t)*CHAR_BIT - 2;      void * addr;   };   struct segmented_addressing   {      std::size_t ctrl     :  2;      std::size_t segment  :  sizeof(std::size_t)*CHAR_BIT - 2;      std::size_t off      :  sizeof(std::size_t)*CHAR_BIT - 2;      std::size_t bits     :  2;   };   union members_t{      relative_addressing  relative;      direct_addressing    direct;      segmented_addressing segmented;   } members;   BOOST_STATIC_ASSERT(sizeof(members_t) == 2*sizeof(std::size_t));   void *relative_calculate_begin_addr() const   {      const std::size_t mask = ~(align - 1);      std::size_t beg = this->members.relative.beg;      return reinterpret_cast<void*>((((std::size_t)this) & mask) - (beg << align_bits));   }   void relative_set_begin_from_base(void *addr)   {      assert(addr < static_cast<void*>(this));      std::size_t off = reinterpret_cast<char*>(this) - reinterpret_cast<char*>(addr);      members.relative.beg = off >> align_bits;   }   //!Obtains the address pointed by the   //!object   std::size_t relative_size() const   {      std::size_t pow  = members.relative.pow;      std::size_t size = (std::size_t(1u) << pow);      assert(pow >= frc_size_bits);      size |= members.relative.frc << (pow - frc_size_bits);      return size;   }   static std::size_t calculate_size(std::size_t orig_size, std::size_t &pow, std::size_t &frc)   {      if(orig_size < align)         orig_size = align;      orig_size = detail::get_rounded_size_po2(orig_size, align);      pow = detail::floor_log2(orig_size);      std::size_t low_size = (std::size_t(1) << pow);      std::size_t diff = orig_size - low_size;      assert(pow >= frc_size_bits);      std::size_t rounded = detail::get_rounded_size_po2                              (diff, (1u << (pow - frc_size_bits)));      if(rounded == low_size){         ++pow;         frc = 0;         rounded  = 0;      }      else{         frc = rounded >> (pow - frc_size_bits);      }      assert(((frc << (pow - frc_size_bits)) & (align-1))==0);      return low_size + rounded;   }   std::size_t get_mode()const   {  return members.direct.ctrl;   }   void set_mode(std::size_t mode)   {      assert(mode < is_max_mode);            members.direct.ctrl = mode;   }   //!Returns true if object represents   //!null pointer   bool is_null() const   {      return   (this->get_mode() < is_relative) &&                !members.direct.dummy &&               !members.direct.addr;   }   //!Sets the object to represent   //!the null pointer   void set_null()   {      if(this->get_mode() >= is_relative){         this->set_mode(is_pointee_outside);      }      members.direct.dummy = 0;      members.direct.addr  = 0;   }   static std::size_t round_size(std::size_t orig_size)   {      std::size_t pow, frc;      return calculate_size(orig_size, pow, frc);   }};//!Configures intersegment_ptr with the capability to address://!2^(sizeof(std::size_t)*CHAR_BIT/2) segment groups//!2^(sizeof(std::size_t)*CHAR_BIT/2) segments per group.//!2^(sizeof(std::size_t)*CHAR_BIT/2)-1 bytes maximum per segment.//!The mapping is implemented through flat_maps synchronized with mutexes.template <class Mutex>struct flat_map_intersegment   :  public intersegment_base{   typedef flat_map_intersegment<Mutex>   self_t;   void set_from_pointer(const volatile void *ptr)   {  this->set_from_pointer(const_cast<const void *>(ptr));  }   //!Obtains the address pointed   //!by the object   void *get_pointer() const   {      if(is_null()){         return 0;      }      switch(this->get_mode()){         case is_relative:            return const_cast<char*>(reinterpret_cast<const char*>(this)) + members.relative.off;         break;         case is_segmented:            {            segment_info_t segment_info;            std::size_t offset;            void *this_base;            get_segment_info_and_offset(this, segment_info, offset, this_base);            char *base  = static_cast<char*>(segment_info.group->address_of(this->members.segmented.segment));            return base + this->members.segmented.off;            }         break;         case is_in_stack:         case is_pointee_outside:            return members.direct.addr;         break;         default:         return 0;         break;      }   }   //!Calculates the distance between two basic_intersegment_ptr-s.   //!This only works with two basic_intersegment_ptr pointing   //!to the same segment. Otherwise undefined   std::ptrdiff_t diff(const self_t &other) const   {  return static_cast<char*>(this->get_pointer()) - static_cast<char*>(other.get_pointer());   }   //!Returns true if both point to   //!the same object   bool equal(const self_t &y) const   {  return this->get_pointer() == y.get_pointer();  }   //!Returns true if *this is less than other.   //!This only works with two basic_intersegment_ptr pointing   //!to the same segment group. Otherwise undefined. Never throws   bool less(const self_t &y) const   {  return this->get_pointer() < y.get_pointer(); }   void swap(self_t &other)   {      void *ptr_this  = this->get_pointer();      void *ptr_other = other.get_pointer();      other.set_from_pointer(ptr_this);      this->set_from_pointer(ptr_other);   }   //!Sets the object internals to represent the   //!address pointed by ptr   void set_from_pointer(const void *ptr)   {      if(!ptr){         this->set_null();         return;      }      std::size_t mode = this->get_mode();      if(mode == is_in_stack){         members.direct.addr = const_cast<void*>(ptr);         return;      }      if(mode == is_relative){         char *beg_addr = static_cast<char*>(this->relative_calculate_begin_addr());         std::size_t seg_size = this->relative_size();         if(ptr >= beg_addr && ptr < (beg_addr + seg_size)){            members.relative.off = static_cast<const char*>(ptr) - reinterpret_cast<const char*>(this);            return;         }      }      std::size_t ptr_offset;      std::size_t this_offset;      segment_info_t ptr_info;      segment_info_t this_info;      void *ptr_base;      void *this_base;      get_segment_info_and_offset(this, this_info, this_offset, this_base);         if(!this_info.group){         this->set_mode(is_in_stack);         this->members.direct.addr = const_cast<void*>(ptr);      }      else{         get_segment_info_and_offset(ptr, ptr_info, ptr_offset, ptr_base);               if(ptr_info.group != this_info.group){            this->set_mode(is_pointee_outside);            this->members.direct.addr =  const_cast<void*>(ptr);         }         else if(ptr_info.id == this_info.id){            this->set_mode(is_relative);            members.relative.off = (static_cast<const char*>(ptr) - reinterpret_cast<const char*>(this));            this->relative_set_begin_from_base(this_base);            std::size_t pow, frc;            std::size_t s = calculate_size(this_info.size, pow, frc);            (void)s;            assert(this_info.size == s);            this->members.relative.pow = pow;            this->members.relative.frc = frc;         }         else{            this->set_mode(is_segmented);            this->members.segmented.segment = ptr_info.id;            this->members.segmented.off     = ptr_offset;         }      }   }   //!Sets the object internals to represent the address pointed    //!by another flat_map_intersegment   void set_from_other(const self_t &other)   {      this->set_from_pointer(other.get_pointer());   }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?