pion-net  4.0.9
common/include/boost/lockfree/detail/tagged_ptr_dcas.hpp
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 */