HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pointerAndBits.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef PXR_BASE_TF_POINTER_AND_BITS_H
25 #define PXR_BASE_TF_POINTER_AND_BITS_H
26 
27 #include "pxr/pxr.h"
28 #include "pxr/base/arch/pragmas.h"
29 
30 #include <cstdint>
31 #include <type_traits>
32 #include <utility>
33 
35 
36 // Return true if \p val is a power of two.
37 constexpr bool Tf_IsPow2(uintptr_t val) {
38  return val && !(val & (val - 1));
39 }
40 
41 /// \class TfPointerAndBits
42 ///
43 /// This class stores a T * and a small integer in the space of a T *. The
44 /// number of bits possible to store depends on the alignment of T. The
45 /// number of distinct values representable by the bits and the maximal value
46 /// are exposed via the compile time constants \a NumBitsValues and \a
47 /// MaxValue, respectively.
48 ///
49 /// The bits may be set and retrieved as any integral type. The pointer value
50 /// and the bits value may be set and retrieved independently.
51 ///
52 template <class T>
54 {
55  // Microsoft Visual Studio doesn't like alignof(<abstract-type>).
56  // We'll assume that such an object has a pointer in it (the vtbl
57  // pointer) and use void* for alignment in that case.
58  template <typename U, bool = false>
59  struct _AlignOf {
60  static constexpr uintptr_t value = alignof(U);
61  };
62  template <typename U>
63  struct _AlignOf<U, true> {
64  static constexpr uintptr_t value = alignof(void*);
65  };
66 
67  // Microsoft Visual Studio doesn't like alignof(<abstract-type>).
68  // We'll assume that such an object has a pointer in it (the vtbl
69  // pointer) and use void* for alignment in that case.
70  static constexpr uintptr_t _GetAlign() noexcept {
72  }
73 
74  static constexpr bool _SupportsAtLeastOneBit() noexcept {
75  return _GetAlign() > 1 && Tf_IsPow2(_GetAlign());
76  }
77 
78 public:
79  /// Constructor. Pointer is initialized to null, bits are initialized to
80  /// zero.
81  constexpr TfPointerAndBits() noexcept : _ptrAndBits(0) {
82  static_assert(_SupportsAtLeastOneBit(),
83  "T's alignment does not support any bits");
84  }
85 
86  /// Constructor. Set the pointer to \a p, and the bits to \a bits.
87  constexpr explicit TfPointerAndBits(T *p, uintptr_t bits = 0) noexcept
88  : _ptrAndBits(_Combine(p, bits))
89  {
90  static_assert(_SupportsAtLeastOneBit(),
91  "T's alignment does not support any bits");
92  }
93 
94  constexpr uintptr_t GetMaxValue() const {
95  return _GetAlign() - 1;
96  }
97 
98  constexpr uintptr_t GetNumBitsValues() const {
99  return _GetAlign();
100  }
101 
102  /// Assignment. Leaves bits unmodified.
104  _SetPtr(ptr);
105  return *this;
106  }
107 
108  /// Indirection.
109  constexpr T *operator->() const noexcept {
110  return _GetPtr();
111  }
112 
113  /// Dereference.
114  constexpr T &operator *() const noexcept {
115  return *_GetPtr();
116  }
117 
118  /// Retrieve the stored bits as the integral type \a Integral.
119  template <class Integral>
120  constexpr Integral BitsAs() const noexcept {
123  // XXX: http://bug/DEV-16691
125  return static_cast<Integral>(_GetBits());
127  }
128 
129  /// Set the stored bits. No static range checking is performed.
130  template <class Integral>
131  void SetBits(Integral val) noexcept {
132  _SetBits(static_cast<uintptr_t>(val));
133  }
134 
135  /// Set the pointer value to \a ptr.
136  void Set(T *ptr) noexcept {
137  _SetPtr(ptr);
138  }
139 
140  /// Set the pointer value to \a ptr and the bits to \a val.
141  template <class Integral>
142  void Set(T *ptr, Integral val) noexcept {
143  _ptrAndBits = _Combine(ptr, val);
144  }
145 
146  /// Retrieve the pointer.
147  constexpr T *Get() const noexcept {
148  return _GetPtr();
149  }
150 
151  /// Retrieve the raw underlying value. This can be useful for doing literal
152  /// equality checks between two instances. The only guarantees are that
153  /// this has the same bit pattern as the pointer value if the bits are 0,
154  /// and will compare equal to another instance when both have identical
155  /// pointer and bits values.
156  constexpr uintptr_t GetLiteral() const noexcept {
157  return _AsInt(_ptrAndBits);
158  }
159 
160  /// Swap this PointerAndBits with \a other.
161  void Swap(TfPointerAndBits &other) noexcept {
162  ::std::swap(_ptrAndBits, other._ptrAndBits);
163  }
164 
165 private:
166  constexpr uintptr_t _GetBitMask() const noexcept {
167  return GetMaxValue();
168  }
169 
170  // Combine \a p and \a bits into a single pointer value.
171  constexpr T *_Combine(T *p, uintptr_t bits) const noexcept {
172  return _AsPtr(_AsInt(p) | (bits & _GetBitMask()));
173  }
174 
175  // Cast the pointer \a p to an integral type. This function and _AsPtr are
176  // the only ones that do the dubious compiler-specific casting.
177  constexpr uintptr_t _AsInt(T *p) const noexcept {
178  return (uintptr_t)p;
179  }
180 
181  // Cast the integral \a i to the pointer type. This function and _AsInt are
182  // the only ones that do the dubious compiler-specific casting.
183  constexpr T *_AsPtr(uintptr_t i) const noexcept {
184  return (T *)i;
185  }
186 
187  // Retrieve the held pointer value.
188  constexpr T *_GetPtr() const noexcept {
189  return _AsPtr(_AsInt(_ptrAndBits) & ~_GetBitMask());
190  }
191 
192  // Set the held pointer value.
193  void _SetPtr(T *p) noexcept {
194  _ptrAndBits = _Combine(p, _GetBits());
195  }
196 
197  // Retrieve the held bits value.
198  constexpr uintptr_t _GetBits() const noexcept {
199  return _AsInt(_ptrAndBits) & _GetBitMask();
200  }
201 
202  // Set the held bits value.
203  void _SetBits(uintptr_t bits) noexcept {
204  _ptrAndBits = _Combine(_GetPtr(), bits);
205  }
206 
207  // Single pointer member stores pointer value and bits.
208  T *_ptrAndBits;
209 };
210 
212 
213 #endif // PXR_BASE_TF_POINTER_AND_BITS_H
#define ARCH_PRAGMA_FORCING_TO_BOOL
Definition: pragmas.h:242
TfPointerAndBits & operator=(T *ptr) noexcept
Assignment. Leaves bits unmodified.
PXR_NAMESPACE_OPEN_SCOPE constexpr bool Tf_IsPow2(uintptr_t val)
void SetBits(Integral val) noexcept
Set the stored bits. No static range checking is performed.
GLsizei const GLfloat * value
Definition: glcorearb.h:824
void Set(T *ptr, Integral val) noexcept
Set the pointer value to ptr and the bits to val.
#define ARCH_PRAGMA_POP
Definition: pragmas.h:170
void swap(T &lhs, T &rhs)
Definition: pugixml.cpp:7172
fallback_uintptr uintptr_t
Definition: format.h:295
constexpr T * Get() const noexcept
Retrieve the pointer.
constexpr TfPointerAndBits() noexcept
constexpr T & operator*() const noexcept
Dereference.
constexpr uintptr_t GetLiteral() const noexcept
#define ARCH_PRAGMA_PUSH
Definition: pragmas.h:166
constexpr uintptr_t GetMaxValue() const
constexpr Integral BitsAs() const noexcept
Retrieve the stored bits as the integral type Integral.
void Set(T *ptr) noexcept
Set the pointer value to ptr.
void Swap(TfPointerAndBits &other) noexcept
Swap this PointerAndBits with other.
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1432
#define ARCH_PRAGMA_MAYBE_UNINITIALIZED
Definition: pragmas.h:186
constexpr uintptr_t GetNumBitsValues() const
auto ptr(T p) -> const void *
Definition: format.h:2448
GLuint GLfloat * val
Definition: glcorearb.h:1608
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:91
Definition: core.h:1131
constexpr TfPointerAndBits(T *p, uintptr_t bits=0) noexcept
Constructor. Set the pointer to p, and the bits to bits.
constexpr T * operator->() const noexcept
Indirection.