source: rrlib_util/tagged_pointer/tTaggedPointerImplementation.h @ 67:e2bb58a307d2

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

Small improvements to tTaggedPointer:

  • Added constructor
  • Added a non-const conversion operator returning reference for use in atomics
  • Introduced common base class for tTaggedPointerImplementation
File size: 7.9 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
75template <typename TStorage>
76class tTaggedPointerImplementationBase
77{
78public:
79
80  typedef TStorage tStorage;
81
82  tTaggedPointerImplementationBase() : storage(0) {}
83
84  tStorage GetStorage() const
85  {
86    return storage;
87  }
88
89  tStorage& GetStorageReference()
90  {
91    return storage;
92  }
93
94  void SetRaw(tStorage raw)
95  {
96    storage = raw;
97  }
98
99protected:
100
101  /*! Current stamp and pointer are stored in this value */
102  tStorage storage;
103};
104
105#if __x86_64__
106
107const uint64_t POINTER16_MASK = 0x0000FFFFFFFFFFFFLL;
108const uint64_t STAMP16_MASK =   0xFFFF000000000000LL;
109const uint64_t POINTER19_MASK = 0x00001FFFFFFFFFFFLL;
110const uint64_t STAMP19_MASK =   0xFFFFE00000000000LL;
111
112/*!
113 * All pointers with up to 16 bits in stamp, use unused 16 bits in pointers on current x64-64 architectures.
114 * If one day, such architectures use these upper 16 bits, we need to do something else - possibly...:
115 * - use 128 bit atomics
116 * - compile with --mx32
117 * - store an index instead of a pointer
118 */
119template <bool ALIGNED_POINTERS>
120class tTaggedPointerImplementation<16, ALIGNED_POINTERS> : public tTaggedPointerImplementationBase<uint64_t>
121{
122public:
123
124  void* GetPointer() const
125  {
126    return reinterpret_cast<void*>(storage & POINTER16_MASK);
127  }
128
129  int GetStamp() const
130  {
131    return static_cast<int>(storage >> 48);
132  }
133
134  void Set(void* pointer, int stamp)
135  {
136    uint64_t pointer_int = reinterpret_cast<uint64_t>(pointer);
137    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).");
138    uint64_t stamp64 = stamp;
139    storage = (stamp64 << 48) | pointer_int;
140  }
141
142  void SetPointer(void* pointer)
143  {
144    uint64_t pointer_int = reinterpret_cast<uint64_t>(pointer);
145    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).");
146    uint64_t old_stamp = storage & STAMP16_MASK;
147    storage = old_stamp | pointer_int;
148  }
149
150  void SetStamp(int stamp)
151  {
152    uint64_t old_pointer = storage & POINTER16_MASK;
153    uint64_t stamp64 = stamp;
154    storage = (stamp64 << 48) | old_pointer;
155  }
156};
157
158template <>
159class tTaggedPointerImplementation<19, true> : public tTaggedPointerImplementationBase<uint64_t>
160{
161public:
162
163  void* GetPointer() const
164  {
165    return reinterpret_cast<void*>((storage & POINTER19_MASK) << 3);
166  }
167
168  int GetStamp() const
169  {
170    return static_cast<int>(storage >> 45);
171  }
172
173  void Set(void* pointer, int stamp)
174  {
175    uint64_t pointer_int = reinterpret_cast<uint64_t>(pointer);
176    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).");
177    uint64_t stamp64 = stamp;
178    storage = (stamp64 << 45) | (pointer_int >> 3);
179  }
180
181  void SetPointer(void* pointer)
182  {
183    uint64_t pointer_int = reinterpret_cast<uint64_t>(pointer);
184    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).");
185    uint64_t old_stamp = storage & STAMP19_MASK;
186    storage = old_stamp | (pointer_int >> 3);
187  }
188
189  void SetStamp(int stamp)
190  {
191    uint64_t old_pointer = storage & POINTER19_MASK;
192    uint64_t stamp64 = stamp;
193    storage = (stamp64 << 45) | old_pointer;
194  }
195};
196
197
198#else
199
200const uint32_t POINTER3_MASK =  0xFFFFFFF8;
201const uint32_t STAMP3_MASK =    0x00000007;
202
203static_assert(sizeof(void*) == 4, "Architecture not supported yet. However, it should not be too much effort to do so.");
204
205template <>
206class tTaggedPointerImplementation<3, true> : public tTaggedPointerImplementationBase<uint>
207{
208public:
209
210  void* GetPointer() const
211  {
212    return reinterpret_cast<void*>(storage & POINTER3_MASK);
213  }
214
215  int GetStamp() const
216  {
217    return static_cast<int>(storage & STAMP3_MASK);
218  }
219
220  void Set(void* pointer, int stamp)
221  {
222    uint pointer_int = reinterpret_cast<uint>(pointer);
223    storage = pointer_int | stamp;
224  }
225
226  void SetPointer(void* pointer)
227  {
228    Set(pointer, GetStamp());
229  }
230
231  void SetStamp(int stamp)
232  {
233    uint old_pointer = storage & POINTER3_MASK;
234    storage = old_pointer | stamp;
235  }
236};
237
238template <bool ALIGNED_POINTERS>
239class tTaggedPointerImplementation<19, ALIGNED_POINTERS>
240{
241public:
242  typedef uint64_t tStorage;
243
244  tTaggedPointerImplementation() : storage(0) {}
245
246  void* GetPointer() const
247  {
248    return reinterpret_cast<void*>(ints[0]);
249  }
250
251  int GetStamp() const
252  {
253    return static_cast<int>(ints[1]);
254  }
255
256  tStorage GetStorage() const
257  {
258    return storage;
259  }
260
261  tStorage& GetStorageReference()
262  {
263    return storage;
264  }
265
266  void Set(void* pointer, int stamp)
267  {
268    SetPointer(pointer);
269    SetStamp(stamp);
270  }
271
272  void SetPointer(void* pointer)
273  {
274    ints[0] = reinterpret_cast<uint>(pointer);
275  }
276
277  void SetRaw(tStorage raw)
278  {
279    storage = raw;
280  }
281
282  void SetStamp(int stamp)
283  {
284    ints[1] = stamp;
285  }
286
287private:
288
289  /*! Current stamp and pointer are stored in this value */
290  union
291  {
292    tStorage storage;
293    uint ints[2]; // int[0] pointer - int[1] stamp
294  };
295};
296
297
298#endif
299
300//----------------------------------------------------------------------
301// End of namespace declaration
302//----------------------------------------------------------------------
303}
304}
305}
306
307
308#endif
Note: See TracBrowser for help on using the repository browser.