1 // tagged pointer, for aba prevention 2 // 3 // Copyright (C) 2008, 2009, 2016 Tim Blechmann, based on code by Cory Nelson 4 // 5 // Distributed under the Boost Software License, Version 1.0. (See 6 // accompanying file LICENSE_1_0.txt or copy at 7 // http://www.boost.org/LICENSE_1_0.txt) 8 9 #ifndef BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED 10 #define BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED 11 12 #include <cstddef> /* for std::size_t */ 13 #include <limits> 14 15 #include <boost/cstdint.hpp> 16 #include <boost/predef.h> 17 18 namespace boost { 19 namespace lockfree { 20 namespace detail { 21 22 #if BOOST_ARCH_X86_64 || defined (__aarch64__) 23 24 template <class T> 25 class tagged_ptr 26 { 27 typedef boost::uint64_t compressed_ptr_t; 28 29 public: 30 typedef boost::uint16_t tag_t; 31 32 private: 33 union cast_unit 34 { 35 compressed_ptr_t value; 36 tag_t tag[4]; 37 }; 38 39 static const int tag_index = 3; 40 static const compressed_ptr_t ptr_mask = 0xffffffffffffUL; //(1L<<48L)-1; 41 extract_ptr(volatile compressed_ptr_t const & i)42 static T* extract_ptr(volatile compressed_ptr_t const & i) 43 { 44 return (T*)(i & ptr_mask); 45 } 46 extract_tag(volatile compressed_ptr_t const & i)47 static tag_t extract_tag(volatile compressed_ptr_t const & i) 48 { 49 cast_unit cu; 50 cu.value = i; 51 return cu.tag[tag_index]; 52 } 53 pack_ptr(T * ptr,tag_t tag)54 static compressed_ptr_t pack_ptr(T * ptr, tag_t tag) 55 { 56 cast_unit ret; 57 ret.value = compressed_ptr_t(ptr); 58 ret.tag[tag_index] = tag; 59 return ret.value; 60 } 61 62 public: 63 /** uninitialized constructor */ tagged_ptr(void)64 tagged_ptr(void) BOOST_NOEXCEPT//: ptr(0), tag(0) 65 {} 66 67 /** copy constructor */ 68 #ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS tagged_ptr(tagged_ptr const & p)69 tagged_ptr(tagged_ptr const & p): 70 ptr(p.ptr) 71 {} 72 #else 73 tagged_ptr(tagged_ptr const & p) = default; 74 #endif 75 tagged_ptr(T * p,tag_t t=0)76 explicit tagged_ptr(T * p, tag_t t = 0): 77 ptr(pack_ptr(p, t)) 78 {} 79 80 /** unsafe set operation */ 81 /* @{ */ 82 #ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS operator =(tagged_ptr const & p)83 tagged_ptr & operator= (tagged_ptr const & p) 84 { 85 ptr = p.ptr; 86 return *this; 87 } 88 #else 89 tagged_ptr & operator= (tagged_ptr const & p) = default; 90 #endif 91 set(T * p,tag_t t)92 void set(T * p, tag_t t) 93 { 94 ptr = pack_ptr(p, t); 95 } 96 /* @} */ 97 98 /** comparing semantics */ 99 /* @{ */ operator ==(volatile tagged_ptr const & p) const100 bool operator== (volatile tagged_ptr const & p) const 101 { 102 return (ptr == p.ptr); 103 } 104 operator !=(volatile tagged_ptr const & p) const105 bool operator!= (volatile tagged_ptr const & p) const 106 { 107 return !operator==(p); 108 } 109 /* @} */ 110 111 /** pointer access */ 112 /* @{ */ get_ptr() const113 T * get_ptr() const 114 { 115 return extract_ptr(ptr); 116 } 117 set_ptr(T * p)118 void set_ptr(T * p) 119 { 120 tag_t tag = get_tag(); 121 ptr = pack_ptr(p, tag); 122 } 123 /* @} */ 124 125 /** tag access */ 126 /* @{ */ get_tag() const127 tag_t get_tag() const 128 { 129 return extract_tag(ptr); 130 } 131 get_next_tag() const132 tag_t get_next_tag() const 133 { 134 tag_t next = (get_tag() + 1u) & (std::numeric_limits<tag_t>::max)(); 135 return next; 136 } 137 set_tag(tag_t t)138 void set_tag(tag_t t) 139 { 140 T * p = get_ptr(); 141 ptr = pack_ptr(p, t); 142 } 143 /* @} */ 144 145 /** smart pointer support */ 146 /* @{ */ operator *() const147 T & operator*() const 148 { 149 return *get_ptr(); 150 } 151 operator ->() const152 T * operator->() const 153 { 154 return get_ptr(); 155 } 156 operator bool(void) const157 operator bool(void) const 158 { 159 return get_ptr() != 0; 160 } 161 /* @} */ 162 163 protected: 164 compressed_ptr_t ptr; 165 }; 166 #else 167 #error unsupported platform 168 #endif 169 170 } /* namespace detail */ 171 } /* namespace lockfree */ 172 } /* namespace boost */ 173 174 #endif /* BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED */ 175