pion-net  4.0.9
tagged_ptr_dcas.hpp
1 // tagged pointer, for aba prevention
2 //
3 // Copyright (C) 2008 Tim Blechmann
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 
9 // Disclaimer: Not a Boost library.
10 
11 #ifndef BOOST_LOCKFREE_TAGGED_PTR_DCAS_HPP_INCLUDED
12 #define BOOST_LOCKFREE_TAGGED_PTR_DCAS_HPP_INCLUDED
13 
14 #include <boost/lockfree/detail/cas.hpp>
15 #include <boost/lockfree/detail/branch_hints.hpp>
16 
17 #include <cstddef> /* for std::size_t */
18 
19 namespace boost
20 {
21 namespace lockfree
22 {
23 
24 template <class T>
25 class BOOST_LOCKFREE_DCAS_ALIGNMENT tagged_ptr
26 {
27 public:
28  typedef std::size_t tag_t;
29 
30  static const bool is_lockfree = boost::lockfree::atomic_cas<tagged_ptr>::is_lockfree;
31 
33  tagged_ptr(void)//: ptr(0), tag(0)
34  {}
35 
37  tagged_ptr(tagged_ptr const & p)//: ptr(0), tag(0)
38  {
39  set(p);
40  }
41 
42  explicit tagged_ptr(T * p, tag_t t = 0):
43  ptr(p), tag(t)
44  {}
45 
47  /* @{ */
48  void operator= (tagged_ptr const & p)
49  {
50  set(p);
51  }
52 
53  void atomic_set(tagged_ptr const & p)
54  {
55  for (;;)
56  {
57  tagged_ptr old;
58  old.set(*this);
59  if(likely(cas(old, p.ptr, p.tag)))
60  return;
61  }
62  }
63 
64  void atomic_set(T * p, tag_t t)
65  {
66  for (;;)
67  {
68  tagged_ptr old;
69  old.set(*this);
70 
71  if(likely(cas(old, p, t)))
72  return;
73  }
74  }
75  /* @} */
76 
78  /* @{ */
79  void set(tagged_ptr const & p)
80  {
81  ptr = p.ptr;
82  tag = p.tag;
83  }
84 
85  void set(T * p, tag_t t)
86  {
87  ptr = p;
88  tag = t;
89  }
90  /* @} */
91 
93  /* @{ */
94  bool operator== (tagged_ptr const & p) const
95  {
96  return (ptr == p.ptr) && (tag == p.tag);
97  }
98 
99  bool operator!= (tagged_ptr const & p) const
100  {
101  return !operator==(p);
102  }
103  /* @} */
104 
106  /* @{ */
107  T * get_ptr() const
108  {
109  return ptr;
110  }
111 
112  void set_ptr(T * p)
113  {
114  ptr = p;
115  }
116  /* @} */
117 
119  /* @{ */
120  tag_t get_tag() const
121  {
122  return tag;
123  }
124 
125  void set_tag(tag_t t)
126  {
127  tag = t;
128  }
129  /* @} */
130 
132  /* @{ */
133  bool cas(tagged_ptr const & oldval, T * newptr)
134  {
135  return cas(oldval, newptr, oldval.tag + 1);
136  }
137 
138  bool cas(tagged_ptr const & oldval, T * newptr, tag_t t)
139  {
140  tagged_ptr newval(newptr, t);
141  return boost::lockfree::atomic_cas<tagged_ptr>::cas(this, oldval, newval);
142  }
143  /* @} */
144 
146  /* @{ */
147  T & operator*() const
148  {
149  return *ptr;
150  }
151 
152  T * operator->() const
153  {
154  return ptr;
155  }
156 
157  operator bool(void) const
158  {
159  return ptr != 0;
160  }
161  /* @} */
162 
163 protected:
164  T * ptr;
165  tag_t tag;
166 };
167 
168 } /* namespace lockfree */
169 } /* namespace boost */
170 
171 #endif /* BOOST_LOCKFREE_TAGGED_PTR_DCAS_HPP_INCLUDED */
bool cas(tagged_ptr const &oldval, T *newptr)
tagged_ptr(tagged_ptr const &p)
void set(tagged_ptr const &p)