00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef BOOST_LOCKFREE_TAGGED_PTR_DCAS_HPP_INCLUDED
00012 #define BOOST_LOCKFREE_TAGGED_PTR_DCAS_HPP_INCLUDED
00013
00014 #include <boost/lockfree/detail/cas.hpp>
00015 #include <boost/lockfree/detail/branch_hints.hpp>
00016
00017 #include <cstddef>
00018
00019 namespace boost
00020 {
00021 namespace lockfree
00022 {
00023
00024 template <class T>
00025 class BOOST_LOCKFREE_DCAS_ALIGNMENT tagged_ptr
00026 {
00027 public:
00028 typedef std::size_t tag_t;
00029
00030 static const bool is_lockfree = boost::lockfree::atomic_cas<tagged_ptr>::is_lockfree;
00031
00033 tagged_ptr(void)
00034 {}
00035
00037 tagged_ptr(tagged_ptr const & p)
00038 {
00039 set(p);
00040 }
00041
00042 explicit tagged_ptr(T * p, tag_t t = 0):
00043 ptr(p), tag(t)
00044 {}
00045
00047
00048 void operator= (tagged_ptr const & p)
00049 {
00050 set(p);
00051 }
00052
00053 void atomic_set(tagged_ptr const & p)
00054 {
00055 for (;;)
00056 {
00057 tagged_ptr old;
00058 old.set(*this);
00059 if(likely(cas(old, p.ptr, p.tag)))
00060 return;
00061 }
00062 }
00063
00064 void atomic_set(T * p, tag_t t)
00065 {
00066 for (;;)
00067 {
00068 tagged_ptr old;
00069 old.set(*this);
00070
00071 if(likely(cas(old, p, t)))
00072 return;
00073 }
00074 }
00075
00076
00078
00079 void set(tagged_ptr const & p)
00080 {
00081 ptr = p.ptr;
00082 tag = p.tag;
00083 }
00084
00085 void set(T * p, tag_t t)
00086 {
00087 ptr = p;
00088 tag = t;
00089 }
00090
00091
00093
00094 bool operator== (tagged_ptr const & p) const
00095 {
00096 return (ptr == p.ptr) && (tag == p.tag);
00097 }
00098
00099 bool operator!= (tagged_ptr const & p) const
00100 {
00101 return !operator==(p);
00102 }
00103
00104
00106
00107 T * get_ptr() const
00108 {
00109 return ptr;
00110 }
00111
00112 void set_ptr(T * p)
00113 {
00114 ptr = p;
00115 }
00116
00117
00119
00120 tag_t get_tag() const
00121 {
00122 return tag;
00123 }
00124
00125 void set_tag(tag_t t)
00126 {
00127 tag = t;
00128 }
00129
00130
00132
00133 bool cas(tagged_ptr const & oldval, T * newptr)
00134 {
00135 return cas(oldval, newptr, oldval.tag + 1);
00136 }
00137
00138 bool cas(tagged_ptr const & oldval, T * newptr, tag_t t)
00139 {
00140 tagged_ptr newval(newptr, t);
00141 return boost::lockfree::atomic_cas<tagged_ptr>::cas(this, oldval, newval);
00142 }
00143
00144
00146
00147 T & operator*() const
00148 {
00149 return *ptr;
00150 }
00151
00152 T * operator->() const
00153 {
00154 return ptr;
00155 }
00156
00157 operator bool(void) const
00158 {
00159 return ptr != 0;
00160 }
00161
00162
00163 protected:
00164 T * ptr;
00165 tag_t tag;
00166 };
00167
00168 }
00169 }
00170
00171 #endif