////////////////////////////////////////////////////////////////////////////// // // (C) Copyright Ion Gaztanaga 2005-2012. 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 #ifndef BOOST_CONFIG_HPP # include #endif # #if defined(BOOST_HAS_PRAGMA_ONCE) # pragma once #endif #include #include // interprocess #include #include #include #include #include //vector #include //set // interprocess/detail #include #include #include #include #include // other boost #include #include //BOOST_STATIC_ASSERT #include #include //BOOST_ASSERT // std #include //CHAR_BIT //!\file //! namespace boost { //Predeclarations template struct has_trivial_constructor; template struct has_trivial_destructor; namespace interprocess { template 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::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(std::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((((std::size_t)this) & mask) - (beg << align_bits)); } void relative_set_begin_from_base(void *addr) { BOOST_ASSERT(addr < static_cast(this)); std::size_t off = reinterpret_cast(this) - reinterpret_cast(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); BOOST_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 = ipcdetail::get_rounded_size_po2(orig_size, align); pow = ipcdetail::floor_log2(orig_size); std::size_t low_size = (std::size_t(1) << pow); std::size_t diff = orig_size - low_size; BOOST_ASSERT(pow >= frc_size_bits); std::size_t rounded = ipcdetail::get_rounded_size_po2 (diff, (std::size_t)(1u << (pow - frc_size_bits))); if(rounded == low_size){ ++pow; frc = 0; rounded = 0; } else{ frc = rounded >> (pow - frc_size_bits); } BOOST_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) { BOOST_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 struct flat_map_intersegment : public intersegment_base { typedef flat_map_intersegment self_t; void set_from_pointer(const volatile void *ptr) { this->set_from_pointer(const_cast(ptr)); } //!Obtains the address pointed //!by the object void *to_raw_pointer() const { if(is_null()){ return 0; } switch(this->get_mode()){ case is_relative: return const_cast(reinterpret_cast(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(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(this->to_raw_pointer()) - static_cast(other.to_raw_pointer()); } //!Returns true if both point to //!the same object bool equal(const self_t &y) const { return this->to_raw_pointer() == y.to_raw_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->to_raw_pointer() < y.to_raw_pointer(); } void swap(self_t &other) { void *ptr_this = this->to_raw_pointer(); void *ptr_other = other.to_raw_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(ptr); return; } if(mode == is_relative){ char *beg_addr = static_cast(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(ptr) - reinterpret_cast(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(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(ptr); } else if(ptr_info.id == this_info.id){ this->set_mode(is_relative); members.relative.off = (static_cast(ptr) - reinterpret_cast(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; BOOST_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.to_raw_pointer()); } //!Increments internal //!offset void inc_offset(std::ptrdiff_t bytes) { this->set_from_pointer(static_cast(this->to_raw_pointer()) + bytes); } //!Decrements internal //!offset void dec_offset(std::ptrdiff_t bytes) { this->set_from_pointer(static_cast(this->to_raw_pointer()) - bytes); } ////////////////////////////////////// ////////////////////////////////////// ////////////////////////////////////// flat_map_intersegment() : intersegment_base() {} ~flat_map_intersegment() {} private: class segment_group_t { struct segment_data { void *addr; std::size_t size; }; vector m_segments; multi_segment_services &m_ms_services; public: segment_group_t(multi_segment_services &ms_services) : m_ms_services(ms_services) {} void push_back(void *addr, std::size_t size) { segment_data d = { addr, size }; m_segments.push_back(d); } void pop_back() { BOOST_ASSERT(!m_segments.empty()); m_segments.erase(--m_segments.end()); } void *address_of(std::size_t segment_id) { BOOST_ASSERT(segment_id < (std::size_t)m_segments.size()); return m_segments[segment_id].addr; } void clear_segments() { m_segments.clear(); } std::size_t get_size() const { return m_segments.size(); } multi_segment_services &get_multi_segment_services() const { return m_ms_services; } friend bool operator< (const segment_group_t&l, const segment_group_t &r) { return &l.m_ms_services < &r.m_ms_services; } }; struct segment_info_t { std::size_t size; std::size_t id; segment_group_t *group; segment_info_t() : size(0), id(0), group(0) {} }; typedef set segment_groups_t; typedef boost::interprocess::flat_map > ptr_to_segment_info_t; struct mappings_t : Mutex { //!Mutex to preserve integrity in multi-threaded //!enviroments typedef Mutex mutex_type; //!Maps base addresses and segment information //!(size and segment group and id)* ptr_to_segment_info_t m_ptr_to_segment_info; ~mappings_t() { //Check that all mappings have been erased BOOST_ASSERT(m_ptr_to_segment_info.empty()); } }; //Static members static mappings_t s_map; static segment_groups_t s_groups; public: typedef segment_group_t* segment_group_id; //!Returns the segment and offset //!of an address static void get_segment_info_and_offset(const void *ptr, segment_info_t &segment, std::size_t &offset, void *&base) { //------------------------------------------------------------------ boost::interprocess::scoped_lock lock(s_map); //------------------------------------------------------------------ base = 0; if(s_map.m_ptr_to_segment_info.empty()){ segment = segment_info_t(); offset = reinterpret_cast(ptr) - static_cast(0); return; } //Find the first base address greater than ptr typename ptr_to_segment_info_t::iterator it = s_map.m_ptr_to_segment_info.upper_bound(ptr); if(it == s_map.m_ptr_to_segment_info.begin()){ segment = segment_info_t(); offset = reinterpret_cast(ptr) - static_cast(0); } //Go to the previous one --it; char * segment_base = const_cast(reinterpret_cast(it->first)); std::size_t segment_size = it->second.size; if(segment_base <= reinterpret_cast(ptr) && (segment_base + segment_size) >= reinterpret_cast(ptr)){ segment = it->second; offset = reinterpret_cast(ptr) - segment_base; base = segment_base; } else{ segment = segment_info_t(); offset = reinterpret_cast(ptr) - static_cast(0); } } //!Associates a segment defined by group/id with a base address and size. //!Returns false if the group is not found or there is an error static void insert_mapping(segment_group_id group_id, void *ptr, std::size_t size) { //------------------------------------------------------------------ boost::interprocess::scoped_lock lock(s_map); //------------------------------------------------------------------ typedef typename ptr_to_segment_info_t::value_type value_type; typedef typename ptr_to_segment_info_t::iterator iterator; typedef std::pair it_b_t; segment_info_t info; info.group = group_id; info.size = size; info.id = group_id->get_size(); it_b_t ret = s_map.m_ptr_to_segment_info.insert(value_type(ptr, info)); BOOST_ASSERT(ret.second); value_eraser v_eraser(s_map.m_ptr_to_segment_info, ret.first); group_id->push_back(ptr, size); v_eraser.release(); } static bool erase_last_mapping(segment_group_id group_id) { //------------------------------------------------------------------ boost::interprocess::scoped_lock lock(s_map); //------------------------------------------------------------------ if(!group_id->get_size()){ return false; } else{ void *addr = group_id->address_of(group_id->get_size()-1); group_id->pop_back(); std::size_t erased = s_map.m_ptr_to_segment_info.erase(addr); (void)erased; BOOST_ASSERT(erased); return true; } } static segment_group_id new_segment_group(multi_segment_services *services) { { //------------------------------------------------------------------ boost::interprocess::scoped_lock lock(s_map); //------------------------------------------------------------------ typedef typename segment_groups_t::iterator iterator; std::pair ret = s_groups.insert(segment_group_t(*services)); BOOST_ASSERT(ret.second); return &*ret.first; } } static bool delete_group(segment_group_id id) { { //------------------------------------------------------------------ boost::interprocess::scoped_lock lock(s_map); //------------------------------------------------------------------ bool success = 1u == s_groups.erase(segment_group_t(*id)); if(success){ typedef typename ptr_to_segment_info_t::iterator ptr_to_segment_info_it; ptr_to_segment_info_it it(s_map.m_ptr_to_segment_info.begin()); while(it != s_map.m_ptr_to_segment_info.end()){ if(it->second.group == id){ it = s_map.m_ptr_to_segment_info.erase(it); } else{ ++it; } } } return success; } } }; //!Static map-segment_info associated with //!flat_map_intersegment<> template typename flat_map_intersegment::mappings_t flat_map_intersegment::s_map; //!Static segment group container associated with //!flat_map_intersegment<> template typename flat_map_intersegment::segment_groups_t flat_map_intersegment::s_groups; //!A smart pointer that can point to a pointee that resides in another memory //!memory mapped or shared memory segment. template class intersegment_ptr : public flat_map_intersegment { typedef flat_map_intersegment PT; typedef intersegment_ptr self_t; typedef PT base_t; void unspecified_bool_type_func() const {} typedef void (self_t::*unspecified_bool_type)() const; public: typedef T * pointer; typedef typename ipcdetail::add_reference::type reference; typedef T value_type; typedef std::ptrdiff_t difference_type; typedef std::random_access_iterator_tag iterator_category; public: //Public Functions //!Constructor from raw pointer (allows "0" pointer conversion). //!Never throws. intersegment_ptr(pointer ptr = 0) { base_t::set_from_pointer(ptr); } //!Constructor from other pointer. //!Never throws. template intersegment_ptr(U *ptr){ base_t::set_from_pointer(pointer(ptr)); } //!Constructor from other intersegment_ptr //!Never throws intersegment_ptr(const intersegment_ptr& ptr) { base_t::set_from_other(ptr); } //!Constructor from other intersegment_ptr. If pointers of pointee types are //!convertible, intersegment_ptrs will be convertibles. Never throws. template intersegment_ptr(const intersegment_ptr &ptr) { pointer p(ptr.get()); (void)p; base_t::set_from_other(ptr); } //!Emulates static_cast operator. //!Never throws. template intersegment_ptr(const intersegment_ptr &r, ipcdetail::static_cast_tag) { base_t::set_from_pointer(static_cast(r.get())); } //!Emulates const_cast operator. //!Never throws. template intersegment_ptr(const intersegment_ptr &r, ipcdetail::const_cast_tag) { base_t::set_from_pointer(const_cast(r.get())); } //!Emulates dynamic_cast operator. //!Never throws. template intersegment_ptr(const intersegment_ptr &r, ipcdetail::dynamic_cast_tag) { base_t::set_from_pointer(dynamic_cast(r.get())); } //!Emulates reinterpret_cast operator. //!Never throws. template intersegment_ptr(const intersegment_ptr &r, ipcdetail::reinterpret_cast_tag) { base_t::set_from_pointer(reinterpret_cast(r.get())); } //!Obtains raw pointer from offset. //!Never throws. pointer get()const { return static_cast(base_t::to_raw_pointer()); } //!Pointer-like -> operator. It can return 0 pointer. //!Never throws. pointer operator->() const { return self_t::get(); } //!Dereferencing operator, if it is a null intersegment_ptr behavior //!is undefined. Never throws. reference operator* () const { return *(self_t::get()); } //!Indexing operator. //!Never throws. reference operator[](std::ptrdiff_t idx) const { return self_t::get()[idx]; } //!Assignment from pointer (saves extra conversion). //!Never throws. intersegment_ptr& operator= (pointer from) { base_t::set_from_pointer(from); return *this; } //!Assignment from other intersegment_ptr. //!Never throws. intersegment_ptr& operator= (const intersegment_ptr &ptr) { base_t::set_from_other(ptr); return *this; } //!Assignment from related intersegment_ptr. If pointers of pointee types //!are assignable, intersegment_ptrs will be assignable. Never throws. template intersegment_ptr& operator= (const intersegment_ptr & ptr) { pointer p(ptr.get()); (void)p; base_t::set_from_other(ptr); return *this; } //!intersegment_ptr + std::ptrdiff_t. //!Never throws. intersegment_ptr operator+ (std::ptrdiff_t idx) const { intersegment_ptr result (*this); result.inc_offset(idx*sizeof(T)); return result; } //!intersegment_ptr - std::ptrdiff_t. //!Never throws. intersegment_ptr operator- (std::ptrdiff_t idx) const { intersegment_ptr result (*this); result.dec_offset(idx*sizeof(T)); return result; } //!intersegment_ptr += std::ptrdiff_t. //!Never throws. intersegment_ptr &operator+= (std::ptrdiff_t offset) { base_t::inc_offset(offset*sizeof(T)); return *this; } //!intersegment_ptr -= std::ptrdiff_t. //!Never throws. intersegment_ptr &operator-= (std::ptrdiff_t offset) { base_t::dec_offset(offset*sizeof(T)); return *this; } //!++intersegment_ptr. //!Never throws. intersegment_ptr& operator++ (void) { base_t::inc_offset(sizeof(T)); return *this; } //!intersegment_ptr++. //!Never throws. intersegment_ptr operator++ (int) { intersegment_ptr temp(*this); ++*this; return temp; } //!--intersegment_ptr. //!Never throws. intersegment_ptr& operator-- (void) { base_t::dec_offset(sizeof(T)); return *this; } //!intersegment_ptr--. //!Never throws. intersegment_ptr operator-- (int) { intersegment_ptr temp(*this); --*this; return temp; } //!Safe bool conversion operator. //!Never throws. operator unspecified_bool_type() const { return base_t::is_null()? 0 : &self_t::unspecified_bool_type_func; } //!Not operator. Not needed in theory, but improves portability. //!Never throws. bool operator! () const { return base_t::is_null(); } //!Swaps two intersegment_ptr-s. More efficient than standard swap. //!Never throws. void swap(intersegment_ptr &other) { base_t::swap(other); } //!Calculates the distance between two intersegment_ptr-s. //!This only works with two basic_intersegment_ptr pointing //!to the same segment. Otherwise undefined template std::ptrdiff_t _diff(const intersegment_ptr &other) const { return base_t::diff(other); } //!Returns true if both point to the //!same object template bool _equal(const intersegment_ptr&other) const { return base_t::equal(other); } //!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 template bool _less(const intersegment_ptr &other) const { return base_t::less(other); } }; //!Compares the equality of two intersegment_ptr-s. //!Never throws. template inline bool operator ==(const intersegment_ptr &left, const intersegment_ptr &right) { //Make sure both pointers can be compared bool e = typename intersegment_ptr::pointer(0) == typename intersegment_ptr::pointer(0); (void)e; return left._equal(right); } //!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 template inline bool operator <(const intersegment_ptr &left, const intersegment_ptr &right) { //Make sure both pointers can be compared bool e = typename intersegment_ptr::pointer(0) < typename intersegment_ptr::pointer(0); (void)e; return left._less(right); } template inline bool operator!= (const intersegment_ptr &pt1, const intersegment_ptr &pt2) { return !(pt1 ==pt2); } //!intersegment_ptr <= intersegment_ptr. //!Never throws. template inline bool operator<= (const intersegment_ptr &pt1, const intersegment_ptr &pt2) { return !(pt1 > pt2); } //!intersegment_ptr > intersegment_ptr. //!Never throws. template inline bool operator> (const intersegment_ptr &pt1, const intersegment_ptr &pt2) { return (pt2 < pt1); } //!intersegment_ptr >= intersegment_ptr. //!Never throws. template inline bool operator>= (const intersegment_ptr &pt1, const intersegment_ptr &pt2) { return !(pt1 < pt2); } //!operator<< template inline std::basic_ostream & operator<< (std::basic_ostream & os, const intersegment_ptr & p) { return os << p.get(); } //!operator>> template inline std::basic_istream & operator>> (std::basic_istream & os, intersegment_ptr & p) { U * tmp; return os >> tmp; p = tmp; } //!std::ptrdiff_t + intersegment_ptr. //!The result is another pointer of the same segment template inline intersegment_ptr operator+ (std::ptrdiff_t diff, const intersegment_ptr& right) { return right + diff; } //!intersegment_ptr - intersegment_ptr. //!This only works with two intersegment_ptr-s that point to the //!same segment template inline std::ptrdiff_t operator- (const intersegment_ptr &pt, const intersegment_ptr &pt2) { return pt._diff(pt2)/sizeof(T); } //! swap specialization template inline void swap (boost::interprocess::intersegment_ptr &pt, boost::interprocess::intersegment_ptr &pt2) { pt.swap(pt2); } //!to_raw_pointer() enables boost::mem_fn to recognize intersegment_ptr. //!Never throws. template inline T * to_raw_pointer(boost::interprocess::intersegment_ptr const & p) { return p.get(); } //!Simulation of static_cast between pointers. //!Never throws. template inline boost::interprocess::intersegment_ptr static_pointer_cast(const boost::interprocess::intersegment_ptr &r) { return boost::interprocess::intersegment_ptr(r, boost::interprocess::ipcdetail::static_cast_tag()); } //!Simulation of const_cast between pointers. //!Never throws. template inline boost::interprocess::intersegment_ptr const_pointer_cast(const boost::interprocess::intersegment_ptr &r) { return boost::interprocess::intersegment_ptr(r, boost::interprocess::ipcdetail::const_cast_tag()); } //!Simulation of dynamic_cast between pointers. //!Never throws. template inline boost::interprocess::intersegment_ptr dynamic_pointer_cast(const boost::interprocess::intersegment_ptr &r) { return boost::interprocess::intersegment_ptr(r, boost::interprocess::ipcdetail::dynamic_cast_tag()); } //!Simulation of reinterpret_cast between pointers. //!Never throws. template inline boost::interprocess::intersegment_ptr reinterpret_pointer_cast(const boost::interprocess::intersegment_ptr &r) { return boost::interprocess::intersegment_ptr(r, boost::interprocess::ipcdetail::reinterpret_cast_tag()); } //!Trait class to detect if an smart pointer has //!multi-segment addressing capabilities. template struct is_multisegment_ptr > { static const bool value = true; }; } //namespace interprocess { #if defined(_MSC_VER) && (_MSC_VER < 1400) //!to_raw_pointer() enables boost::mem_fn to recognize intersegment_ptr. //!Never throws. template inline T * to_raw_pointer(boost::interprocess::intersegment_ptr const & p) { return p.get(); } #endif //!has_trivial_constructor<> == true_type specialization //!for optimizations template struct has_trivial_constructor < boost::interprocess::intersegment_ptr > : public true_type{}; //!has_trivial_destructor<> == true_type specialization //!for optimizations template struct has_trivial_destructor < boost::interprocess::intersegment_ptr > : public true_type{}; } //namespace boost { #if 0 //bits //-> is_segmented //-> is_relative //-> is_in_stack //-> is_pointee_outside //Data //segmented: // // std::size_t ctrl : CTRL_BITS; // std::size_t segment : MAX_SEGMENT_BITS; // std::size_t offset; //RELATIVE_SIZE_BITS = SIZE_T_BITS - // MAX_SEGMENT_BITS - // CTRL_BITS 10 10 //MAX_SEGMENT_SIZE = SIZE_T_BITS - ALIGN_BITS 20 52 //SIZE_T_BITS - 1 - ALIGN_BITS 19 51 //POW_SIZE_BITS = upper_log2 // (SIZE_T_BITS - 1 - ALIGN_BITS) 5 6 //FRC_SIZE_BITS = SIZE_T_BITS - CTRL_BITS // MAX_SEGMENT_SIZE_ALIGNBITS - POW_SIZE_BITS 6 5 //relative: // // std::size_t ctrl : CTRL_BITS; 2 2 // std::size_t size_pow : POW_SIZE_BITS 5 6 // std::size_t size_frc : FRC_SIZE_BITS; 6 5 // std::size_t start : MAX_SEGMENT_SIZE_ALIGNBITS;19 51 // std::ptrdiff_t distance : SIZE_T_BITS; 32 64 //direct: // // std::size_t ctrl : CTRL_BITS; 2 2 // std::size_t dummy : SIZE_T_BITS - CTRL_BITS 30 62 // void *addr : SIZE_T_BITS; 32 64 //32 bits systems: //Page alignment: 2**12 // //!Obtains the address pointed by the //!object void *to_raw_pointer() const { if(this->is_pointee_outside() || this->is_in_stack()){ return raw_address(); } else if(this->is_relative()){ return (const_cast(reinterpret_cast(this))) + this->relative_pointee_offset(); } else{ group_manager *m = get_segment_group_manager(addr); char *base = static_cast(m->get_id_address(this->segmented_id())); return base + this->segmented_offset(); } } void set_from_pointer(const void *ptr) { if(!ptr){ this->set_pointee_outside(); this->raw_address(ptr); } else if(this->is_in_stack()){ this->raw_address(ptr); } else if(this->is_relative() && ( (ptr >= this->relative_start()) &&(ptr < this->relative_start() + this->relative_size())) ){ this->relative_offset(ptr - this); } else{ segment_info_t ptr_info = get_id_from_addr(ptr); segment_info_t this_info = get_id_from_addr(this); if(ptr_info.segment_group != this_info.segment_group){ if(!ptr_info.segment_group){ this->set_in_stack(); } else{ this->set_pointee_outside(); } } else if(ptr_info.segment_id == this_info.segment_id){ set_relative(); this->relative_size (ptr_info.size); this->relative_offset(static_cast(ptr) - reinterpret_cast(this)); this->relative_start (ptr_info.base); } } } void set_from_other(const self_t &other) { this->set_from_pointer(other.to_raw_pointer()); } #endif #include #endif //#ifndef BOOST_INTERPROCESS_INTERSEGMENT_PTR_HPP