# 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 */