pion-net
4.0.9
|
00001 // tagged pointer, for aba prevention 00002 // 00003 // Copyright (C) 2008 Tim Blechmann 00004 // 00005 // Distributed under the Boost Software License, Version 1.0. (See 00006 // accompanying file LICENSE_1_0.txt or copy at 00007 // http://www.boost.org/LICENSE_1_0.txt) 00008 00009 // Disclaimer: Not a Boost library. 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> /* for std::size_t */ 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)//: ptr(0), tag(0) 00034 {} 00035 00037 tagged_ptr(tagged_ptr const & p)//: ptr(0), tag(0) 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 } /* namespace lockfree */ 00169 } /* namespace boost */ 00170 00171 #endif /* BOOST_LOCKFREE_TAGGED_PTR_DCAS_HPP_INCLUDED */