00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED
00012 #define BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED
00013
00014 #include <boost/lockfree/detail/cas.hpp>
00015 #include <boost/lockfree/detail/branch_hints.hpp>
00016
00017 #include <cstddef>
00018
00019 #include <boost/cstdint.hpp>
00020
00021 namespace boost
00022 {
00023 namespace lockfree
00024 {
00025
00026 #if defined (__x86_64__) || defined (_M_X64)
00027
00028 template <class T>
00029 class BOOST_LOCKFREE_DCAS_ALIGNMENT tagged_ptr
00030 {
00031 typedef boost::uint64_t compressed_ptr_t;
00032 typedef boost::uint16_t tag_t;
00033
00034 private:
00035 union cast_unit
00036 {
00037 compressed_ptr_t value;
00038 tag_t tag[4];
00039 };
00040
00041 static const int tag_index = 3;
00042 static const compressed_ptr_t ptr_mask = 0xffffffffffff;
00043
00044 static T* extract_ptr(compressed_ptr_t const & i)
00045 {
00046 return (T*)(i & ptr_mask);
00047 }
00048
00049 static tag_t extract_tag(compressed_ptr_t const & i)
00050 {
00051 cast_unit cu;
00052 cu.value = i;
00053 return cu.tag[tag_index];
00054 }
00055
00056 static compressed_ptr_t pack_ptr(T * ptr, int tag)
00057 {
00058 cast_unit ret;
00059 ret.value = compressed_ptr_t(ptr);
00060 ret.tag[tag_index] = tag;
00061 return ret.value;
00062 }
00063
00064 public:
00065 static const bool is_lockfree = boost::lockfree::atomic_cas<compressed_ptr_t>::is_lockfree;
00066
00068 tagged_ptr(void)
00069 {}
00070
00072 tagged_ptr(tagged_ptr const & p)
00073 {
00074 set(p);
00075 }
00076
00077 explicit tagged_ptr(T * p, tag_t t = 0):
00078 ptr(pack_ptr(p, t))
00079 {}
00080
00082
00083 void operator= (tagged_ptr const & p)
00084 {
00085 atomic_set(p);
00086 }
00087
00088 void atomic_set(tagged_ptr const & p)
00089 {
00090 set(p);
00091 }
00092
00093 void atomic_set(T * p, tag_t t)
00094 {
00095 ptr = pack_ptr(p, t);
00096 }
00097
00098
00100
00101 void set(tagged_ptr const & p)
00102 {
00103 ptr = p.ptr;
00104 }
00105
00106 void set(T * p, tag_t t)
00107 {
00108 ptr = pack_ptr(p, t);
00109 }
00110
00111
00113
00114 bool operator== (tagged_ptr const & p) const
00115 {
00116 return (ptr == p.ptr);
00117 }
00118
00119 bool operator!= (tagged_ptr const & p) const
00120 {
00121 return !operator==(p);
00122 }
00123
00124
00126
00127 T * get_ptr() const
00128 {
00129 return extract_ptr(ptr);
00130 }
00131
00132 void set_ptr(T * p)
00133 {
00134 tag_t tag = get_tag();
00135 ptr = pack_ptr(p, tag);
00136 }
00137
00138
00140
00141 tag_t get_tag() const
00142 {
00143 return extract_tag(ptr);
00144 }
00145
00146 void set_tag(tag_t t)
00147 {
00148 T * p = get_ptr();
00149 ptr = pack_ptr(p, t);
00150 }
00151
00152
00154
00155 private:
00156 bool cas(compressed_ptr_t const & oldval, compressed_ptr_t const & newval)
00157 {
00158 return boost::lockfree::atomic_cas<compressed_ptr_t>::cas(&(this->ptr), oldval, newval);
00159 }
00160
00161 public:
00162 bool cas(tagged_ptr const & oldval, T * newptr)
00163 {
00164 compressed_ptr_t new_compressed_ptr = pack_ptr(newptr, extract_tag(oldval.ptr)+1);
00165 return cas(oldval.ptr, new_compressed_ptr);
00166 }
00167
00168 bool cas(tagged_ptr const & oldval, T * newptr, tag_t t)
00169 {
00170 compressed_ptr_t new_compressed_ptr = pack_ptr(newptr, t);
00171 return boost::lockfree::atomic_cas<compressed_ptr_t>::cas(&(this->ptr), oldval.ptr, new_compressed_ptr);
00172 }
00173
00174
00176
00177 T & operator*() const
00178 {
00179 return *get_ptr();
00180 }
00181
00182 T * operator->() const
00183 {
00184 return get_ptr();
00185 }
00186
00187 operator bool(void) const
00188 {
00189 return get_ptr() != 0;
00190 }
00191
00192
00193 protected:
00194 compressed_ptr_t ptr;
00195 };
00196 #else
00197 #error unsupported platform
00198 #endif
00199
00200 }
00201 }
00202
00203 #endif