// tagged pointer, for aba prevention // // Copyright (C) 2008, 2009, 2016 Tim Blechmann, based on code by Cory Nelson // // 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) #ifndef BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED #define BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED #include /* for std::size_t */ #include #include #include namespace boost { namespace lockfree { namespace detail { #if BOOST_ARCH_X86_64 || defined (__aarch64__) template class tagged_ptr { typedef boost::uint64_t compressed_ptr_t; public: typedef boost::uint16_t tag_t; private: union cast_unit { compressed_ptr_t value; tag_t tag[4]; }; static const int tag_index = 3; static const compressed_ptr_t ptr_mask = 0xffffffffffffUL; //(1L<<48L)-1; static T* extract_ptr(volatile compressed_ptr_t const & i) { return (T*)(i & ptr_mask); } static tag_t extract_tag(volatile compressed_ptr_t const & i) { cast_unit cu; cu.value = i; return cu.tag[tag_index]; } static compressed_ptr_t pack_ptr(T * ptr, tag_t tag) { cast_unit ret; ret.value = compressed_ptr_t(ptr); ret.tag[tag_index] = tag; return ret.value; } public: /** uninitialized constructor */ tagged_ptr(void) BOOST_NOEXCEPT//: ptr(0), tag(0) {} /** copy constructor */ #ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS tagged_ptr(tagged_ptr const & p): ptr(p.ptr) {} #else tagged_ptr(tagged_ptr const & p) = default; #endif explicit tagged_ptr(T * p, tag_t t = 0): ptr(pack_ptr(p, t)) {} /** unsafe set operation */ /* @{ */ #ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS tagged_ptr & operator= (tagged_ptr const & p) { ptr = p.ptr; return *this; } #else tagged_ptr & operator= (tagged_ptr const & p) = default; #endif void set(T * p, tag_t t) { ptr = pack_ptr(p, t); } /* @} */ /** comparing semantics */ /* @{ */ bool operator== (volatile tagged_ptr const & p) const { return (ptr == p.ptr); } bool operator!= (volatile tagged_ptr const & p) const { return !operator==(p); } /* @} */ /** pointer access */ /* @{ */ T * get_ptr() const { return extract_ptr(ptr); } void set_ptr(T * p) { tag_t tag = get_tag(); ptr = pack_ptr(p, tag); } /* @} */ /** tag access */ /* @{ */ tag_t get_tag() const { return extract_tag(ptr); } tag_t get_next_tag() const { tag_t next = (get_tag() + 1u) & (std::numeric_limits::max)(); return next; } void set_tag(tag_t t) { T * p = get_ptr(); ptr = pack_ptr(p, t); } /* @} */ /** smart pointer support */ /* @{ */ T & operator*() const { return *get_ptr(); } T * operator->() const { return get_ptr(); } operator bool(void) const { return get_ptr() != 0; } /* @} */ protected: compressed_ptr_t ptr; }; #else #error unsupported platform #endif } /* namespace detail */ } /* namespace lockfree */ } /* namespace boost */ #endif /* BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED */