HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
typeDispatchTable.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_TYPE_DISPATCH_TABLE_H
8 #define PXR_EXEC_VDF_TYPE_DISPATCH_TABLE_H
9 
10 /// \file
11 
12 /// This file defines VdfTypeDispatchTable, a template that can be used to
13 /// perform runtime type dispatch.
14 
15 #include "pxr/pxr.h"
16 
17 #include "pxr/exec/vdf/api.h"
18 
19 #include "pxr/base/tf/hash.h"
21 #include "pxr/base/tf/type.h"
22 
23 #include <tbb/spin_rw_mutex.h>
24 
25 #include <typeinfo>
26 #include <utility>
27 
29 
30 // Non-template-dependent part of dispatch table implementation.
32 {
33 public:
34  /// Returns \c true if a function has been registered for type \p t.
35  VDF_API
36  bool IsTypeRegistered(TfType t) const;
37 
38 protected:
39  /// Register function pointer \p f as the implementation to dispatch to
40  /// for type \p ti.
41  VDF_API
42  bool _RegisterType(const std::type_info &ti, void *f);
43 
44  /// Find a registered function pointer for type \p t. Issues a fatal
45  /// error if no function has been registered for type \p t.
46  VDF_API
47  void *_FindOrFatalError(TfType t) const;
48 
49  VDF_API
51 
52  VDF_API
54 
55 private:
56  // Type for the dispatch map, a map from keys to functions.
58 
59  // The type dispatch map.
60  _MapType _map;
61 
62  // Guards the hash table buckets.
63  mutable tbb::spin_rw_mutex _mutex;
64 };
65 
66 
67 /// Dispatches calls to template instantiations based on a TfType that is
68 /// determined at runtime.
69 ///
70 /// Parameters:
71 ///
72 /// \p Fn is a class template where \c Fn<T>::Call(...) is a static function to
73 /// be dispatched on type \c T. Note that the function signature cannot
74 /// depend on the template argument and \c Fn<int>::Call(...) must be a
75 /// valid instantiation even if \c int is never registered as a type.
76 ///
77 ///
78 /// The given function is instantiated once for each of the types registered
79 /// using \c RegisterType. The resulting function pointers are called using
80 /// the \c Call() member function.
81 ///
82 ///
83 /// Example:
84 ///
85 /// Given this class template to be instantiated for each attribute type that
86 /// may be computed:
87 /// \code
88 /// template <typename T>
89 /// struct _ExtractExecValue {
90 /// static VtValue Call(const VdfVector &v, int offset)
91 /// {
92 /// const auto accessor = v.GetReadAccessor<T>();
93 /// return VtValue(accessor[offset]);
94 /// }
95 /// };
96 /// \endcode
97 ///
98 /// This call defines a statically initialized type dispatch table that
99 /// dispatches calls to \c _ExtractExecValue, keyed off attribute types:
100 /// \code
101 /// TF_MAKE_STATIC_DATA(VdfTypeDispatchTable<_ExtractExecValue>,
102 /// _extractTable)
103 /// {
104 /// _extractTable->RegisterType<AttributeType0>();
105 /// _extractTable->RegisterType<AttributeType1>();
106 /// // ...
107 /// _extractTable->RegisterType<AttributeTypeN>();
108 /// }
109 /// \endcode
110 ///
111 /// This code calls an instance of \c _ExtractExecValue, keyed off the
112 /// type of \c attribute:
113 /// \code
114 /// VtValue value = _extractTable->Call<VtValue>()(
115 /// attribute.GetTypeName().GetType(), v, offset);
116 /// \endcode
117 ///
118 template <template <typename> class Fn>
121 {
122 public:
123  /// The signature of the functions dispatched by the table.
124  ///
125  /// \c Fn<int> is special only because it was the default instantiation
126  /// used by the previous VdfTypeDispatchTable implementation to determine
127  /// the function type for all \c Fn<T>.
128  ///
129  using FnSignature = decltype(Fn<int>::Call);
130 
131  /// Register an additional type with the type dispatch table. This will
132  /// return \c true, if \p Type has been successfully added to the dispatch
133  /// table and \c false if it was registered already.
134  ///
135  template <typename Type>
137  {
138  // Instantiate Fn for the given type, and put a pointer to it in
139  // the type dispatch map.
140  const std::type_info &ti = typeid(Type);
141  FnSignature *f = &Fn<Type>::Call;
142  return _RegisterType(ti, reinterpret_cast<void *>(f));
143  }
144 
145  /// Invoke the function registered for \p key type.
146  ///
147  /// Calling this with an unregistered type is a fatal error.
148  ///
149  template <typename RetType, typename... Args>
150  RetType Call(TfType key, Args&&... args) const
151  {
152  return reinterpret_cast<FnSignature *>(this->_FindOrFatalError(key))
153  (std::forward<Args>(args)...);
154  }
155 };
156 
158 
159 #endif
#define PXR_NAMESPACE_OPEN_SCOPE
Definition: pxr.h:73
VDF_API bool IsTypeRegistered(TfType t) const
Returns true if a function has been registered for type t.
#define VDF_API
Definition: api.h:25
GLfloat f
Definition: glcorearb.h:1926
RetType Call(TfType key, Args &&...args) const
VDF_API Vdf_TypeDispatchTableBase()
GLdouble t
Definition: glad.h:2397
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74
**If you just want to fire and args
Definition: thread.h:618
Definition: type.h:47
decltype(_CreateEmptyVector< int >::Call) FnSignature
VDF_API ~Vdf_TypeDispatchTableBase()
VDF_API void * _FindOrFatalError(TfType t) const
VDF_API bool _RegisterType(const std::type_info &ti, void *f)