source: rrlib_util/tagged_pointer/tTaggedPointerImplementation.h @ 65:f2d25876bbc5

Last change on this file since 65:f2d25876bbc5 was 65:f2d25876bbc5, checked in by Max Reichardt <mreichardt@…>, 7 years ago

Added tagged pointer class and test program.

File size: 8.3 KB
Line 
1//
2// You received this file as part of RRLib
3// Robotics Research Library
4//
5// Copyright (C) Finroc GbR (finroc.org)
6//
7// This program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public License
9// as published by the Free Software Foundation; either version 2
10// of the License, or (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20//
21//----------------------------------------------------------------------
22/*!\file    rrlib/util/tagged_pointer/tTaggedPointerImplementation.h
23 *
24 * \author  Max Reichardt
25 *
26 * \date    2012-10-09
27 *
28 * \brief   Contains tTaggedPointerImplementation
29 *
30 * \b tTaggedPointerImplementation
31 *
32 * Tagged pointer implementations for different platforms
33 *
34 */
35//----------------------------------------------------------------------
36#ifndef __rrlib__util__tagged_pointer__tTaggedPointerImplementation_h__
37#define __rrlib__util__tagged_pointer__tTaggedPointerImplementation_h__
38
39//----------------------------------------------------------------------
40// External includes (system with <>, local with "")
41//----------------------------------------------------------------------
42#include <cassert>
43
44//----------------------------------------------------------------------
45// Internal includes with ""
46//----------------------------------------------------------------------
47
48//----------------------------------------------------------------------
49// Namespace declaration
50//----------------------------------------------------------------------
51namespace rrlib
52{
53namespace util
54{
55namespace tagged_pointer
56{
57
58//----------------------------------------------------------------------
59// Forward declarations / typedefs / enums
60//----------------------------------------------------------------------
61
62//----------------------------------------------------------------------
63// Class declaration
64//----------------------------------------------------------------------
65//! Tagged pointer implementations for different platforms
66/*!
67 * Tagged pointer implementations for different platforms
68 * Template is specialized for different platforms later
69 */
70template <uint TAG_BIT_WIDTH, bool ALIGNED_POINTERS>
71class tTaggedPointerImplementation : public tTaggedPointerImplementation < TAG_BIT_WIDTH + 1, ALIGNED_POINTERS >
72{
73};
74
75#if __x86_64__
76
77const uint64_t POINTER16_MASK = 0x0000FFFFFFFFFFFFLL;
78const uint64_t STAMP16_MASK =   0xFFFF000000000000LL;
79const uint64_t POINTER19_MASK = 0x00001FFFFFFFFFFFLL;
80const uint64_t STAMP19_MASK =   0xFFFFE00000000000LL;
81
82/*!
83 * All pointers with up to 16 bits in stamp, use unused 16 bits in pointers on current x64-64 architectures.
84 * If one day, such architectures use these upper 16 bits, we need to do something else - possibly...:
85 * - use 128 bit atomics
86 * - compile with --mx32
87 * - store an index instead of a pointer
88 */
89template <bool ALIGNED_POINTERS>
90class tTaggedPointerImplementation<16, ALIGNED_POINTERS>
91{
92public:
93  typedef uint64_t tStorage;
94
95  tTaggedPointerImplementation() : storage(0) {}
96
97  void* GetPointer() const
98  {
99    return reinterpret_cast<void*>(storage & POINTER16_MASK);
100  }
101
102  int GetStamp() const
103  {
104    return static_cast<int>(storage >> 48);
105  }
106
107  tStorage GetStorage() const
108  {
109    return storage;
110  }
111
112  void Set(void* pointer, int stamp)
113  {
114    uint64_t pointer_int = reinterpret_cast<uint64_t>(pointer);
115    assert((pointer_int & POINTER16_MASK) == pointer_int && "x86-64 pointers are using the high 16 bits now. Implementation needs to be changed (see comment to this class).");
116    uint64_t stamp64 = stamp;
117    storage = (stamp64 << 48) | pointer_int;
118  }
119
120  void SetPointer(void* pointer)
121  {
122    uint64_t pointer_int = reinterpret_cast<uint64_t>(pointer);
123    assert((pointer_int & POINTER16_MASK) == pointer_int && "x86-64 pointers are using the high 16 bits now. Implementation needs to be changed (see comment to this class).");
124    uint64_t old_stamp = storage & STAMP16_MASK;
125    storage = old_stamp | pointer_int;
126  }
127
128  void SetRaw(tStorage raw)
129  {
130    storage = raw;
131  }
132
133  void SetStamp(int stamp)
134  {
135    uint64_t old_pointer = storage & POINTER16_MASK;
136    uint64_t stamp64 = stamp;
137    storage = (stamp64 << 48) | old_pointer;
138  }
139
140private:
141
142  /*! Current stamp and pointer are stored in this value */
143  tStorage storage;
144};
145
146template <>
147class tTaggedPointerImplementation<19, true>
148{
149public:
150  typedef uint64_t tStorage;
151
152  tTaggedPointerImplementation() : storage(0) {}
153  tTaggedPointerImplementation(tStorage raw) : storage(raw) {}
154
155  void* GetPointer() const
156  {
157    return reinterpret_cast<void*>((storage & POINTER19_MASK) << 3);
158  }
159
160  int GetStamp() const
161  {
162    return static_cast<int>(storage >> 45);
163  }
164
165  tStorage GetStorage() const
166  {
167    return storage;
168  }
169
170  void Set(void* pointer, int stamp)
171  {
172    uint64_t pointer_int = reinterpret_cast<uint64_t>(pointer);
173    assert((pointer_int & POINTER16_MASK) == pointer_int && "x86-64 pointers are using the high 16 bits now. Implementation needs to be changed (see comment to this class).");
174    uint64_t stamp64 = stamp;
175    storage = (stamp64 << 45) | (pointer_int >> 3);
176  }
177
178  void SetPointer(void* pointer)
179  {
180    uint64_t pointer_int = reinterpret_cast<uint64_t>(pointer);
181    assert((pointer_int & POINTER16_MASK) == pointer_int && "x86-64 pointers are using the high 16 bits now. Implementation needs to be changed (see comment to this class).");
182    uint64_t old_stamp = storage & STAMP19_MASK;
183    storage = old_stamp | (pointer_int >> 3);
184  }
185
186  void SetRaw(tStorage raw)
187  {
188    storage = raw;
189  }
190
191  void SetStamp(int stamp)
192  {
193    uint64_t old_pointer = storage & POINTER19_MASK;
194    uint64_t stamp64 = stamp;
195    storage = (stamp64 << 45) | old_pointer;
196  }
197
198private:
199
200  /*! Current stamp and pointer are stored in this value */
201  tStorage storage;
202};
203
204
205#else
206
207const uint32_t POINTER3_MASK =  0xFFFFFFF8;
208const uint32_t STAMP3_MASK =    0x00000007;
209
210static_assert(sizeof(void*) == 4, "Architecture not supported yet. However, it should not be too much effort to do so.")
211
212template <>
213class tTaggedPointerImplementation<3, true>
214{
215public:
216  typedef uint tStorage;
217
218  tTaggedPointerImplementation() : storage(0) {}
219  tTaggedPointerImplementation(tStorage raw) : storage(raw) {}
220
221  void* GetPointer() const
222  {
223    return reinterpret_cast<void*>(storage & POINTER3_MASK);
224  }
225
226  int GetStamp() const
227  {
228    return static_cast<int>(storage & STAMP3_MASK);
229  }
230
231  tStorage GetStorage() const
232  {
233    return storage;
234  }
235
236  void Set(void* pointer, int stamp)
237  {
238    uint pointer_int = reinterpret_cast<uint>(pointer);
239    storage = pointer_int | stamp;
240  }
241
242  void SetPointer(void* pointer)
243  {
244    Set(pointer, GetStamp());
245  }
246
247  void SetRaw(tStorage raw)
248  {
249    storage = raw;
250  }
251
252  void SetStamp(int stamp)
253  {
254    uint old_pointer = storage & POINTER3_MASK;
255    storage = old_pointer | stamp;
256  }
257
258private:
259
260  /*! Current stamp and pointer are stored in this value */
261  tStorage storage;
262};
263
264template <bool ALIGNED_POINTERS>
265class tTaggedPointerImplementation<19, ALIGNED_POINTERS>
266{
267public:
268  typedef uint64_t tStorage;
269
270  tTaggedPointerImplementation() : storage(0) {}
271  tTaggedPointerImplementation(tStorage raw) : storage(raw) {}
272
273  void* GetPointer() const
274  {
275    return reinterpret_cast<void*>(ints[0]);
276  }
277
278  int GetStamp() const
279  {
280    return static_cast<int>(ints[1]);
281  }
282
283  tStorage GetStorage() const
284  {
285    return storage;
286  }
287
288  void Set(void* pointer, int stamp)
289  {
290    SetPointer(pointer);
291    SetStamp(stamp);
292  }
293
294  void SetPointer(void* pointer)
295  {
296    ints[0] = reinterpret_cast<uint>(pointer);
297  }
298
299  void SetRaw(tStorage raw)
300  {
301    storage = raw;
302  }
303
304  void SetStamp(int stamp)
305  {
306    ints[1] = stamp;
307  }
308
309private:
310
311  /*! Current stamp and pointer are stored in this value */
312  union
313  {
314    tStorage storage;
315    uint ints[2]; // int[0] pointer - int[1] stamp
316  };
317};
318
319
320#endif
321
322//----------------------------------------------------------------------
323// End of namespace declaration
324//----------------------------------------------------------------------
325}
326}
327}
328
329
330#endif
Note: See TracBrowser for help on using the repository browser.