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