Zero  0.1.0
w_markable_pointer.h
Go to the documentation of this file.
1 /*
2  * (c) Copyright 2014, Hewlett-Packard Development Company, LP
3  */
4 #ifndef __W_MARKABLE_POINTER_H
5 #define __W_MARKABLE_POINTER_H
6 
7 #include "w_defines.h"
8 #include <cstdint>
9 #include <cassert>
10 #include <iostream>
11 #include "AtomicCounter.hpp"
12 
45 typedef uint16_t aba_stamp;
46 
114 template<class T>
116 public:
118  static const uint64_t MARK_BIT = 0x0000000000000001LL;
119 
121  static const uint64_t POINTER_MASK = 0x0000FFFFFFFFFFFELL;
122 
124  static const uint64_t STAMP_SHIFT = 48;
125 
127  static const uint64_t STAMP_MASK = 0xFFFF000000000000LL;
128 
131 
133  MarkablePointer(T* pointer, bool mark, aba_stamp stamp = 0)
134  : _pointer(combine(pointer, mark, stamp)) {}
135 
138  operator=(other);
139  }
140 
143  // ACCESS_ONCE semantics to make it at least regular.
144  _pointer = static_cast<const volatile uintptr_t&>(other._pointer);
145  return *this;
146  }
147 
151  bool operator==(const MarkablePointer& other) const {
152  return _pointer == other._pointer;
153  }
154 
158  bool operator!=(const MarkablePointer& other) const {
159  return _pointer != other._pointer;
160  }
161 
166  void set_mark(bool on) {
167  _pointer = (_pointer & ~MARK_BIT) | (on ? MARK_BIT : 0);
168  }
169 
171  bool is_marked() const {
172  return (_pointer & MARK_BIT) != 0;
173  }
174 
177  return (_pointer & STAMP_MASK) >> STAMP_SHIFT;
178  }
179 
181  void set_aba_stamp(aba_stamp stamp) {
182  uint64_t stamp_shifted = static_cast<uint64_t>(stamp) << STAMP_SHIFT;
183  _pointer = (_pointer & (~STAMP_MASK)) | stamp_shifted;
184  }
185 
188  _pointer += (1LL << STAMP_SHIFT);
189  }
190 
192  T* get_pointer() const {
193  return cast_to_ptr(_pointer & POINTER_MASK);
194  }
195 
197  T* operator->() const {
198  return get_pointer();
199  }
200 
202  bool is_null() const {
203  return (_pointer & POINTER_MASK) == 0;
204  }
205 
207  uint64_t as_int() const {
208  return _pointer;
209  }
210 
222  bool atomic_cas(T* expected_pointer, T* new_pointer,
223  bool expected_mark, bool new_mark,
224  aba_stamp expected_stamp, aba_stamp new_stamp);
225 
232  bool atomic_cas(const MarkablePointer& expected,
233  const MarkablePointer& desired);
234 
241 
245  static uintptr_t combine(T* ptr, bool mark, aba_stamp stamp) {
246  assert((cast_to_int(ptr) & (~POINTER_MASK)) == 0);
247  uint64_t stamp_shifted = static_cast<uint64_t>(stamp) << STAMP_SHIFT;
248  return cast_to_int(ptr) | (mark ? MARK_BIT : 0) | stamp_shifted;
249  }
250 
252  static uintptr_t cast_to_int(T* ptr) {
253  return reinterpret_cast<uintptr_t>(reinterpret_cast<void*>(ptr));
254  }
255 
257  static T* cast_to_ptr(uintptr_t ptr) {
258  return reinterpret_cast<T*>(reinterpret_cast<void*>(ptr));
259  }
260 
261 protected:
263  uintptr_t _pointer;
264 };
265 
291 template<class NEXT>
293  MarkablePointerChain() : next() {}
294 
296  : next(other.next) {}
297 
299  next = other.next;
300  return *this;
301  }
302 
305 };
306 
307 template<class T>
308 inline bool MarkablePointer<T>::atomic_cas(T* expected_pointer, T* desired_pointer,
309  bool expected_mark, bool desired_mark, aba_stamp expected_stamp,
310  aba_stamp new_stamp) {
311  uintptr_t expected = combine(expected_pointer, expected_mark, expected_stamp);
312  uintptr_t desired = combine(desired_pointer, desired_mark, new_stamp);
313  return lintel::unsafe::atomic_compare_exchange_strong<uintptr_t>(
314  &_pointer, &expected, desired);
315 }
316 
317 template<class T>
319  const MarkablePointer& desired) {
320  uintptr_t expected_tmp = expected._pointer;
321  return lintel::unsafe::atomic_compare_exchange_strong<uintptr_t>(
322  &_pointer, &expected_tmp, desired._pointer);
323 }
324 
325 template<class T>
327  uintptr_t old = lintel::unsafe::atomic_exchange<uintptr_t>(&_pointer, new_ptr._pointer);
328  MarkablePointer<T> ret;
329  ret._pointer = old;
330  return ret;
331 }
332 
333 template<class T>
334 inline std::ostream& operator<<(std::ostream& o, const MarkablePointer<T>& x) {
335  o << "Markable pointer ";
336  if (x.is_null()) {
337  o << "<NULL>";
338  } else {
339  o << x.as_int() << " <marked=" << x.is_marked() << ", stamp=" << x.get_aba_stamp()
340  << ", ptr=" << *(x.get_pointer()) << ">";
341  }
342  return o;
343 }
344 
345 #endif // __W_MARKABLE_POINTER_H
static uintptr_t cast_to_int(T *ptr)
Definition: w_markable_pointer.h:252
bool operator!=(const MarkablePointer &other) const
Definition: w_markable_pointer.h:158
bool operator==(const MarkablePointer &other) const
Definition: w_markable_pointer.h:151
aba_stamp get_aba_stamp() const
Definition: w_markable_pointer.h:176
MarkablePointer & operator=(const MarkablePointer< T > &other)
Definition: w_markable_pointer.h:142
Header file for lintel::Atomic class.
uint16_t aba_stamp
Definition: w_markable_pointer.h:45
uint64_t as_int() const
Definition: w_markable_pointer.h:207
static uintptr_t combine(T *ptr, bool mark, aba_stamp stamp)
Definition: w_markable_pointer.h:245
MarkablePointer(const MarkablePointer< T > &other)
Definition: w_markable_pointer.h:137
static const uint64_t STAMP_MASK
Definition: w_markable_pointer.h:127
MarkablePointer atomic_swap(const MarkablePointer &new_ptr)
[Atomic] Swap pointer, mark, and stamp altogether.
Definition: w_markable_pointer.h:326
MarkablePointerChain(const MarkablePointerChain &other)
Definition: w_markable_pointer.h:295
static const uint64_t POINTER_MASK
Definition: w_markable_pointer.h:121
bool is_marked() const
Definition: w_markable_pointer.h:171
void increase_aba_stamp()
Definition: w_markable_pointer.h:187
void set_aba_stamp(aba_stamp stamp)
Definition: w_markable_pointer.h:181
uintptr_t _pointer
Definition: w_markable_pointer.h:263
bool is_null() const
Definition: w_markable_pointer.h:202
Bit-stealing Atomic Markable Pointer.
Definition: w_markable_pointer.h:115
void set_mark(bool on)
Definition: w_markable_pointer.h:166
MarkablePointerChain()
Definition: w_markable_pointer.h:293
MarkablePointer(T *pointer, bool mark, aba_stamp stamp=0)
Definition: w_markable_pointer.h:133
T * get_pointer() const
Definition: w_markable_pointer.h:192
MarkablePointer< NEXT > next
Definition: w_markable_pointer.h:304
MarkablePointerChain & operator=(const MarkablePointerChain &other)
Definition: w_markable_pointer.h:298
#define T
Definition: w_okvl_inl.h:45
MarkablePointer()
Definition: w_markable_pointer.h:130
static T * cast_to_ptr(uintptr_t ptr)
Definition: w_markable_pointer.h:257
T * operator->() const
Definition: w_markable_pointer.h:197
Atomic Markable Pointer Chain for lock-free list/queue/etc.
Definition: w_markable_pointer.h:292
static const uint64_t STAMP_SHIFT
Definition: w_markable_pointer.h:124
bool atomic_cas(T *expected_pointer, T *new_pointer, bool expected_mark, bool new_mark, aba_stamp expected_stamp, aba_stamp new_stamp)
[Atomic] Compare and set for both pointer and mark (stashed value). See Figure 9.23 of [HERLIHY] ...
Definition: w_markable_pointer.h:308
static const uint64_t MARK_BIT
Definition: w_markable_pointer.h:118