]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | #ifdef BOOST_ARCH_X86_64 | |
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 | ||
42 | static T* extract_ptr(volatile compressed_ptr_t const & i) | |
43 | { | |
44 | return (T*)(i & ptr_mask); | |
45 | } | |
46 | ||
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 | ||
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 */ | |
64 | tagged_ptr(void) BOOST_NOEXCEPT//: ptr(0), tag(0) | |
65 | {} | |
66 | ||
67 | /** copy constructor */ | |
68 | #ifdef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS | |
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 | ||
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 | |
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 | ||
92 | void set(T * p, tag_t t) | |
93 | { | |
94 | ptr = pack_ptr(p, t); | |
95 | } | |
96 | /* @} */ | |
97 | ||
98 | /** comparing semantics */ | |
99 | /* @{ */ | |
100 | bool operator== (volatile tagged_ptr const & p) const | |
101 | { | |
102 | return (ptr == p.ptr); | |
103 | } | |
104 | ||
105 | bool operator!= (volatile tagged_ptr const & p) const | |
106 | { | |
107 | return !operator==(p); | |
108 | } | |
109 | /* @} */ | |
110 | ||
111 | /** pointer access */ | |
112 | /* @{ */ | |
113 | T * get_ptr() const | |
114 | { | |
115 | return extract_ptr(ptr); | |
116 | } | |
117 | ||
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 | /* @{ */ | |
127 | tag_t get_tag() const | |
128 | { | |
129 | return extract_tag(ptr); | |
130 | } | |
131 | ||
132 | 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 | ||
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 | /* @{ */ | |
147 | T & operator*() const | |
148 | { | |
149 | return *get_ptr(); | |
150 | } | |
151 | ||
152 | T * operator->() const | |
153 | { | |
154 | return get_ptr(); | |
155 | } | |
156 | ||
157 | 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 */ |