• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  tagged pointer, for aba prevention
2 //
3 //  Copyright (C) 2008, 2009, 2016 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 #ifndef BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED
10 #define BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED
11 
12 #include <cstddef>              /* for std::size_t */
13 #include <limits>
14 
15 #include <boost/cstdint.hpp>
16 #include <boost/predef.h>
17 
18 namespace boost {
19 namespace lockfree {
20 namespace detail {
21 
22 #if BOOST_ARCH_X86_64 || defined (__aarch64__)
23 
24 template <class T>
25 class tagged_ptr
26 {
27     typedef boost::uint64_t compressed_ptr_t;
28 
29 public:
30     typedef boost::uint16_t tag_t;
31 
32 private:
33     union cast_unit
34     {
35         compressed_ptr_t value;
36         tag_t tag[4];
37     };
38 
39     static const int tag_index = 3;
40     static const compressed_ptr_t ptr_mask = 0xffffffffffffUL; //(1L<<48L)-1;
41 
extract_ptr(volatile compressed_ptr_t const & i)42     static T* extract_ptr(volatile compressed_ptr_t const & i)
43     {
44         return (T*)(i & ptr_mask);
45     }
46 
extract_tag(volatile compressed_ptr_t const & i)47     static tag_t extract_tag(volatile compressed_ptr_t const & i)
48     {
49         cast_unit cu;
50         cu.value = i;
51         return cu.tag[tag_index];
52     }
53 
pack_ptr(T * ptr,tag_t tag)54     static compressed_ptr_t pack_ptr(T * ptr, tag_t tag)
55     {
56         cast_unit ret;
57         ret.value = compressed_ptr_t(ptr);
58         ret.tag[tag_index] = tag;
59         return ret.value;
60     }
61 
62 public:
63     /** uninitialized constructor */
tagged_ptr(void)64     tagged_ptr(void) BOOST_NOEXCEPT//: ptr(0), tag(0)
65     {}
66 
67     /** copy constructor */
68 #ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
tagged_ptr(tagged_ptr const & p)69     tagged_ptr(tagged_ptr const & p):
70         ptr(p.ptr)
71     {}
72 #else
73     tagged_ptr(tagged_ptr const & p) = default;
74 #endif
75 
tagged_ptr(T * p,tag_t t=0)76     explicit tagged_ptr(T * p, tag_t t = 0):
77         ptr(pack_ptr(p, t))
78     {}
79 
80     /** unsafe set operation */
81     /* @{ */
82 #ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS
operator =(tagged_ptr const & p)83     tagged_ptr & operator= (tagged_ptr const & p)
84     {
85          ptr = p.ptr;
86          return *this;
87     }
88 #else
89     tagged_ptr & operator= (tagged_ptr const & p) = default;
90 #endif
91 
set(T * p,tag_t t)92     void set(T * p, tag_t t)
93     {
94         ptr = pack_ptr(p, t);
95     }
96     /* @} */
97 
98     /** comparing semantics */
99     /* @{ */
operator ==(volatile tagged_ptr const & p) const100     bool operator== (volatile tagged_ptr const & p) const
101     {
102         return (ptr == p.ptr);
103     }
104 
operator !=(volatile tagged_ptr const & p) const105     bool operator!= (volatile tagged_ptr const & p) const
106     {
107         return !operator==(p);
108     }
109     /* @} */
110 
111     /** pointer access */
112     /* @{ */
get_ptr() const113     T * get_ptr() const
114     {
115         return extract_ptr(ptr);
116     }
117 
set_ptr(T * p)118     void set_ptr(T * p)
119     {
120         tag_t tag = get_tag();
121         ptr = pack_ptr(p, tag);
122     }
123     /* @} */
124 
125     /** tag access */
126     /* @{ */
get_tag() const127     tag_t get_tag() const
128     {
129         return extract_tag(ptr);
130     }
131 
get_next_tag() const132     tag_t get_next_tag() const
133     {
134         tag_t next = (get_tag() + 1u) & (std::numeric_limits<tag_t>::max)();
135         return next;
136     }
137 
set_tag(tag_t t)138     void set_tag(tag_t t)
139     {
140         T * p = get_ptr();
141         ptr = pack_ptr(p, t);
142     }
143     /* @} */
144 
145     /** smart pointer support  */
146     /* @{ */
operator *() const147     T & operator*() const
148     {
149         return *get_ptr();
150     }
151 
operator ->() const152     T * operator->() const
153     {
154         return get_ptr();
155     }
156 
operator bool(void) const157     operator bool(void) const
158     {
159         return get_ptr() != 0;
160     }
161     /* @} */
162 
163 protected:
164     compressed_ptr_t ptr;
165 };
166 #else
167 #error unsupported platform
168 #endif
169 
170 } /* namespace detail */
171 } /* namespace lockfree */
172 } /* namespace boost */
173 
174 #endif /* BOOST_LOCKFREE_TAGGED_PTR_PTRCOMPRESSION_HPP_INCLUDED */
175