HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
fixedSizePolymorphicHolder.h
Go to the documentation of this file.
1 //
2 // Copyright 2025 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_EXEC_VDF_FIXED_SIZE_POLYMORPHIC_HOLDER_H
8 #define PXR_EXEC_VDF_FIXED_SIZE_POLYMORPHIC_HOLDER_H
9 
10 #include "pxr/pxr.h"
11 
12 #include "pxr/base/arch/defines.h"
13 #include "pxr/base/arch/pragmas.h"
15 
16 #include <utility>
17 #include <type_traits>
18 
20 
21 ///
22 /// \class Vdf_FixedSizePolymorphicHolder
23 ///
24 /// Used to implement small object optimizations for the type-erasure (Any)
25 /// pattern.
26 ///
27 /// This class allows clients to instantiate polymorphic objects into a fixed
28 /// buffer space. If code attempts to instantiate an object that is too large to
29 /// fit in the allotted space, that code will generate a compile-time error.
30 /// Additionally, any instance of a derived class stored in this holder must
31 /// have its \p Base object at the same address. Practically speaking, this
32 /// means that multiple inheritance isn't supported. Currently this requirement
33 /// is enforced only at runtime.
34 ///
35 template <class Base, size_t BufferSize>
37 {
38  static_assert(std::is_polymorphic<Base>::value, "");
39 
40  // The storage used to contain instances.
41  using _Storage = typename std::aligned_storage_t<BufferSize, sizeof(void *)>;
42 
43 public:
44 
45  // Noncopyable.
47  Vdf_FixedSizePolymorphicHolder const &) = delete;
49  operator=(Vdf_FixedSizePolymorphicHolder const &) = delete;
50 
52 
53  /// Creates an instance
54  ///
55  /// Uses placement-new to create an object of type \p Derived into the local
56  /// storage. Will fail to compile if \p Derived's size or alignment is
57  /// incompatible with the storage.
58  template <class Derived, class ... Args>
59  void New(Args && ... args) {
60  static_assert(
62  "Derived is not a derived class of Base.");
63  static_assert(
64  sizeof(Derived) <= sizeof(_Storage),
65  "The size of the derived type is larger than the availble storage.");
66  static_assert(
67  alignof(_Storage) % alignof(Derived) == 0,
68  "The derived type has incompatible alignment.");
69  new (_GetStorage()) Derived(std::forward<Args>(args)...);
70  // Verification that Base and Derived start at the same address.
71  // Perhaps this can be done at compile-time?
72  void *const bStart =
73  static_cast<Base *>(static_cast<Derived *>(_GetStorage()));
74  TF_AXIOM(bStart == _GetStorage());
75  }
76 
77  /// Destroys a held instance
78  ///
79  /// Invokes `~Base` on the held object. A valid instance of type Base or a
80  /// type derived from Base must already be held.
81  void Destroy() {
82 #if defined(ARCH_COMPILER_GCC) && ARCH_COMPILER_GCC_MAJOR < 11
85 #endif
86  Get()->~Base();
87 #if defined(ARCH_COMPILER_GCC) && ARCH_COMPILER_GCC_MAJOR < 11
89 #endif
90  }
91 
92  /// Returns a Base pointer to the held instance.
93  inline Base const *Get() const {
94  return static_cast<Base const *>(_GetStorage());
95  }
96 
97  /// Returns a Base pointer to the held instance.
98  inline Base *Get() {
99  return static_cast<Base *>(_GetStorage());
100  }
101 
102 private:
103 
104  // Returns a pointer to the instance storage space.
105  inline void *_GetStorage() {
106  return &_storage;
107  }
108 
109  // Returns a pointer to the instance storage space.
110  inline void const *_GetStorage() const {
111  return &_storage;
112  }
113 
114 
115  //
116  // Data Members
117  //
118 
119  _Storage _storage;
120 };
121 
123 
124 #endif
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
GLsizei const GLfloat * value
Definition: glcorearb.h:824
#define ARCH_PRAGMA_POP
Definition: pragmas.h:170
#define ARCH_PRAGMA_PUSH
Definition: pragmas.h:166
Base * Get()
Returns a Base pointer to the held instance.
#define TF_AXIOM(cond)
#define ARCH_PRAGMA_MAYBE_UNINITIALIZED
Definition: pragmas.h:186
Base const * Get() const
Returns a Base pointer to the held instance.
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
**If you just want to fire and args
Definition: thread.h:618
Vdf_FixedSizePolymorphicHolder & operator=(Vdf_FixedSizePolymorphicHolder const &)=delete