pion-net  4.0.9
tagged_ptr_ptrcompression.hpp
1 // tagged pointer, for aba prevention
2 //
3 // Copyright (C) 2008, 2009 Tim Blechmann, based on code by Cory Nelson
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_PTRCOMPRESSION_HPP_INCLUDED
12 #define BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_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 #include <boost/cstdint.hpp>
20 
21 namespace boost
22 {
23 namespace lockfree
24 {
25 
26 #if defined (__x86_64__) || defined (_M_X64)
27 
28 template <class T>
29 class BOOST_LOCKFREE_DCAS_ALIGNMENT tagged_ptr
30 {
31  typedef boost::uint64_t compressed_ptr_t;
32  typedef boost::uint16_t tag_t;
33 
34 private:
35  union cast_unit
36  {
37  compressed_ptr_t value;
38  tag_t tag[4];
39  };
40 
41  static const int tag_index = 3;
42  static const compressed_ptr_t ptr_mask = 0xffffffffffff; //(1L<<48L)-1;
43 
44  static T* extract_ptr(compressed_ptr_t const & i)
45  {
46  return (T*)(i & ptr_mask);
47  }
48 
49  static tag_t extract_tag(compressed_ptr_t const & i)
50  {
51  cast_unit cu;
52  cu.value = i;
53  return cu.tag[tag_index];
54  }
55 
56  static compressed_ptr_t pack_ptr(T * ptr, int tag)
57  {
58  cast_unit ret;
59  ret.value = compressed_ptr_t(ptr);
60  ret.tag[tag_index] = tag;
61  return ret.value;
62  }
63 
64 public:
65  static const bool is_lockfree = boost::lockfree::atomic_cas<compressed_ptr_t>::is_lockfree;
66 
68  tagged_ptr(void)//: ptr(0), tag(0)
69  {}
70 
72  tagged_ptr(tagged_ptr const & p)//: ptr(0), tag(0)
73  {
74  set(p);
75  }
76 
77  explicit tagged_ptr(T * p, tag_t t = 0):
78  ptr(pack_ptr(p, t))
79  {}
80 
82  /* @{ */
83  void operator= (tagged_ptr const & p)
84  {
85  atomic_set(p);
86  }
87 
88  void atomic_set(tagged_ptr const & p)
89  {
90  set(p);
91  }
92 
93  void atomic_set(T * p, tag_t t)
94  {
95  ptr = pack_ptr(p, t);
96  }
97  /* @} */
98 
100  /* @{ */
101  void set(tagged_ptr const & p)
102  {
103  ptr = p.ptr;
104  }
105 
106  void set(T * p, tag_t t)
107  {
108  ptr = pack_ptr(p, t);
109  }
110  /* @} */
111 
113  /* @{ */
114  bool operator== (tagged_ptr const & p) const
115  {
116  return (ptr == p.ptr);
117  }
118 
119  bool operator!= (tagged_ptr const & p) const
120  {
121  return !operator==(p);
122  }
123  /* @} */
124 
126  /* @{ */
127  T * get_ptr() const
128  {
129  return extract_ptr(ptr);
130  }
131 
132  void set_ptr(T * p)
133  {
134  tag_t tag = get_tag();
135  ptr = pack_ptr(p, tag);
136  }
137  /* @} */
138 
140  /* @{ */
141  tag_t get_tag() const
142  {
143  return extract_tag(ptr);
144  }
145 
146  void set_tag(tag_t t)
147  {
148  T * p = get_ptr();
149  ptr = pack_ptr(p, t);
150  }
151  /* @} */
152 
154  /* @{ */
155 private:
156  bool cas(compressed_ptr_t const & oldval, compressed_ptr_t const & newval)
157  {
158  return boost::lockfree::atomic_cas<compressed_ptr_t>::cas(&(this->ptr), oldval, newval);
159  }
160 
161 public:
162  bool cas(tagged_ptr const & oldval, T * newptr)
163  {
164  compressed_ptr_t new_compressed_ptr = pack_ptr(newptr, extract_tag(oldval.ptr)+1);
165  return cas(oldval.ptr, new_compressed_ptr);
166  }
167 
168  bool cas(tagged_ptr const & oldval, T * newptr, tag_t t)
169  {
170  compressed_ptr_t new_compressed_ptr = pack_ptr(newptr, t);
171  return boost::lockfree::atomic_cas<compressed_ptr_t>::cas(&(this->ptr), oldval.ptr, new_compressed_ptr);
172  }
173  /* @} */
174 
176  /* @{ */
177  T & operator*() const
178  {
179  return *get_ptr();
180  }
181 
182  T * operator->() const
183  {
184  return get_ptr();
185  }
186 
187  operator bool(void) const
188  {
189  return get_ptr() != 0;
190  }
191  /* @} */
192 
193 protected:
194  compressed_ptr_t ptr;
195 };
196 #else
197 #error unsupported platform
198 #endif
199 
200 } /* namespace lockfree */
201 } /* namespace boost */
202 
203 #endif /* BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED */