Plasma Engine  2.0
Loading...
Searching...
No Matches
RTTI.h
1#pragma once
2
4
5#include <Foundation/Basics.h>
6#include <Foundation/Configuration/Plugin.h>
7#include <Foundation/Memory/Allocator.h>
8#include <Foundation/Reflection/Implementation/StaticRTTI.h>
9
10// *****************************************
11// ***** Runtime Type Information Data *****
12
13struct plRTTIAllocator;
19class plMessage;
20using plMessageId = plUInt16;
21
29class PL_FOUNDATION_DLL plRTTI
30{
31public:
33 plRTTI(plStringView sName, const plRTTI* pParentType, plUInt32 uiTypeSize, plUInt32 uiTypeVersion, plUInt8 uiVariantType,
36 plArrayPtr<plMessageSenderInfo> messageSenders, const plRTTI* (*fnVerifyParent)());
37
38
39 ~plRTTI();
40
42 void VerifyCorrectness() const;
43
45 static void VerifyCorrectnessForAllTypes();
46
48 PL_ALWAYS_INLINE plStringView GetTypeName() const { return m_sTypeName; } // [tested]
49
51 PL_ALWAYS_INLINE plUInt64 GetTypeNameHash() const { return m_uiTypeNameHash; } // [tested]
52
54 PL_ALWAYS_INLINE const plRTTI* GetParentType() const { return m_pParentType; } // [tested]
55
57 PL_ALWAYS_INLINE plVariantType::Enum GetVariantType() const { return static_cast<plVariantType::Enum>(m_uiVariantType); }
58
60 PL_ALWAYS_INLINE bool IsDerivedFrom(const plRTTI* pBaseType) const // [tested]
61 {
62 const plUInt32 thisGeneration = m_ParentHierarchy.GetCount();
63 const plUInt32 baseGeneration = pBaseType->m_ParentHierarchy.GetCount();
64 PL_ASSERT_DEBUG(thisGeneration > 0 && baseGeneration > 0, "SetupParentHierarchy() has not been called");
65 return thisGeneration >= baseGeneration && m_ParentHierarchy.GetData()[thisGeneration - baseGeneration] == pBaseType;
66 }
67
69 template <typename BASE>
70 PL_ALWAYS_INLINE bool IsDerivedFrom() const // [tested]
71 {
72 return IsDerivedFrom(plGetStaticRTTI<BASE>());
73 }
74
76 PL_ALWAYS_INLINE plRTTIAllocator* GetAllocator() const { return m_pAllocator; } // [tested]
77
79 PL_ALWAYS_INLINE plArrayPtr<const plAbstractProperty* const> GetProperties() const { return m_Properties; } // [tested]
80
81 PL_ALWAYS_INLINE plArrayPtr<const plAbstractFunctionProperty* const> GetFunctions() const { return m_Functions; }
82
83 PL_ALWAYS_INLINE plArrayPtr<const plPropertyAttribute* const> GetAttributes() const { return m_Attributes; }
84
86 template <typename Type>
87 const Type* GetAttributeByType() const;
88
90 void GetAllProperties(plDynamicArray<const plAbstractProperty*>& out_properties) const; // [tested]
91
93 PL_ALWAYS_INLINE plUInt32 GetTypeSize() const { return m_uiTypeSize; } // [tested]
94
96 PL_ALWAYS_INLINE plUInt32 GetTypeVersion() const { return m_uiTypeVersion; }
97
99 PL_ALWAYS_INLINE const plBitflags<plTypeFlags>& GetTypeFlags() const { return m_TypeFlags; } // [tested]
100
102 static const plRTTI* FindTypeByName(plStringView sName); // [tested]
103
105 static const plRTTI* FindTypeByNameHash(plUInt64 uiNameHash); // [tested]
106 static const plRTTI* FindTypeByNameHash32(plUInt32 uiNameHash);
107
108 using PredicateFunc = plDelegate<bool(const plRTTI*), 48>;
110 static const plRTTI* FindTypeIf(PredicateFunc func);
111
113 const plAbstractProperty* FindPropertyByName(plStringView sName, bool bSearchBaseTypes = true) const; // [tested]
114
116 PL_ALWAYS_INLINE plStringView GetPluginName() const { return m_sPluginName; } // [tested]
117
119 PL_ALWAYS_INLINE const plArrayPtr<plAbstractMessageHandler*>& GetMessageHandlers() const { return m_MessageHandlers; }
120
123 bool DispatchMessage(void* pInstance, plMessage& ref_msg) const;
124
127 bool DispatchMessage(const void* pInstance, plMessage& ref_msg) const;
128
130 template <typename MessageType>
131 PL_ALWAYS_INLINE bool CanHandleMessage() const
132 {
133 return CanHandleMessage(MessageType::GetTypeMsgId());
134 }
135
137 inline bool CanHandleMessage(plMessageId id) const
138 {
139 PL_ASSERT_DEBUG(m_uiMsgIdOffset != plSmallInvalidIndex, "Message handler table should have been gathered at this point.\n"
140 "If this assert is triggered for a type loaded from a dynamic plugin,\n"
141 "you may have forgotten to instantiate an plPlugin object inside your plugin DLL.");
142
143 const plUInt32 uiIndex = id - m_uiMsgIdOffset;
144 return uiIndex < m_DynamicMessageHandlers.GetCount() && m_DynamicMessageHandlers.GetData()[uiIndex] != nullptr;
145 }
146
147 PL_ALWAYS_INLINE const plArrayPtr<plMessageSenderInfo>& GetMessageSender() const { return m_MessageSenders; }
148
150 {
151 using StorageType = plUInt8;
152
153 enum Enum
154 {
155 None = 0,
156 ExcludeNonAllocatable = PL_BIT(0),
157 ExcludeAbstract = PL_BIT(1),
158 ExcludeNotConcrete = ExcludeNonAllocatable | ExcludeAbstract,
159
160 Default = None
161 };
162
163 struct Bits
164 {
165 plUInt8 ExcludeNonAllocatable : 1;
166 plUInt8 ExcludeAbstract : 1;
167 };
168 };
169
170 using VisitorFunc = plDelegate<void(const plRTTI*), 48>;
171 static void ForEachType(VisitorFunc func, plBitflags<ForEachOptions> options = ForEachOptions::Default); // [tested]
172
173 static void ForEachDerivedType(const plRTTI* pBaseType, VisitorFunc func, plBitflags<ForEachOptions> options = ForEachOptions::Default);
174
175 template <typename T>
176 static PL_ALWAYS_INLINE void ForEachDerivedType(VisitorFunc func, plBitflags<ForEachOptions> options = ForEachOptions::Default)
177 {
178 ForEachDerivedType(plGetStaticRTTI<T>(), func, options);
179 }
180
181protected:
182 plStringView m_sPluginName;
183 plStringView m_sTypeName;
187 void UpdateType(const plRTTI* pParentType, plUInt32 uiTypeSize, plUInt32 uiTypeVersion, plUInt8 uiVariantType, plBitflags<plTypeFlags> flags);
188 void RegisterType();
189 void UnregisterType();
190
191 void GatherDynamicMessageHandlers();
192 void SetupParentHierarchy();
193
194 const plRTTI* m_pParentType = nullptr;
195 plRTTIAllocator* m_pAllocator = nullptr;
196
197 plUInt32 m_uiTypeSize = 0;
198 plUInt32 m_uiTypeVersion = 0;
199 plUInt64 m_uiTypeNameHash = 0;
200 plUInt32 m_uiTypeIndex = 0;
201 plBitflags<plTypeFlags> m_TypeFlags;
202 plUInt8 m_uiVariantType = 0;
203 plUInt16 m_uiMsgIdOffset = plSmallInvalidIndex;
204
205 const plRTTI* (*m_VerifyParent)();
206
208 plSmallArray<plAbstractMessageHandler*, 1, plStaticsAllocatorWrapper> m_DynamicMessageHandlers; // do not track this data, it won't be deallocated before shutdown
209
210 plArrayPtr<plMessageSenderInfo> m_MessageSenders;
212
213private:
214 PL_MAKE_SUBSYSTEM_STARTUP_FRIEND(Foundation, Reflection);
215
217 static void AssignPlugin(plStringView sPluginName);
218
219 static void SanityCheckType(plRTTI* pType);
220
222 static void PluginEventHandler(const plPluginEvent& EventData);
223};
224
225PL_DECLARE_FLAGS_OPERATORS(plRTTI::ForEachOptions);
226
227
228// ***********************************
229// ***** Object Allocator Struct *****
230
231
233struct PL_FOUNDATION_DLL plRTTIAllocator
234{
235 virtual ~plRTTIAllocator();
236
238 virtual bool CanAllocate() const { return true; } // [tested]
239
241 template <typename T>
243 {
244 return AllocateInternal(pAllocator).Cast<T>();
245 }
246
248 template <typename T>
249 plInternal::NewInstance<T> Clone(const void* pObject, plAllocator* pAllocator = nullptr)
250 {
251 return CloneInternal(pObject, pAllocator).Cast<T>();
252 }
253
255 virtual void Deallocate(void* pObject, plAllocator* pAllocator = nullptr) = 0; // [tested]
256
257private:
258 virtual plInternal::NewInstance<void> AllocateInternal(plAllocator* pAllocator) = 0;
259 virtual plInternal::NewInstance<void> CloneInternal(const void* pObject, plAllocator* pAllocator)
260 {
261 PL_REPORT_FAILURE("Cloning is not supported by this allocator.");
262 return plInternal::NewInstance<void>(nullptr, pAllocator);
263 }
264};
265
267struct PL_FOUNDATION_DLL plRTTINoAllocator : public plRTTIAllocator
268{
270 virtual bool CanAllocate() const override { return false; } // [tested]
271
273 virtual plInternal::NewInstance<void> AllocateInternal(plAllocator* pAllocator) override // [tested]
274 {
275 PL_REPORT_FAILURE("This function should never be called.");
276 return plInternal::NewInstance<void>(nullptr, pAllocator);
277 }
278
280 virtual void Deallocate(void* pObject, plAllocator* pAllocator) override // [tested]
281 {
282 PL_REPORT_FAILURE("This function should never be called.");
283 }
284};
285
287template <typename CLASS, typename AllocatorWrapper = plDefaultAllocatorWrapper>
289{
291 virtual plInternal::NewInstance<void> AllocateInternal(plAllocator* pAllocator) override // [tested]
292 {
293 if (pAllocator == nullptr)
294 {
295 pAllocator = AllocatorWrapper::GetAllocator();
296 }
297
298 return PL_NEW(pAllocator, CLASS);
299 }
300
302 virtual plInternal::NewInstance<void> CloneInternal(const void* pObject, plAllocator* pAllocator) override // [tested]
303 {
304 if (pAllocator == nullptr)
305 {
306 pAllocator = AllocatorWrapper::GetAllocator();
307 }
308
309 return CloneImpl(pObject, pAllocator, plTraitInt<std::is_copy_constructible<CLASS>::value>());
310 }
311
313 virtual void Deallocate(void* pObject, plAllocator* pAllocator) override // [tested]
314 {
315 if (pAllocator == nullptr)
316 {
317 pAllocator = AllocatorWrapper::GetAllocator();
318 }
319
320 CLASS* pPointer = static_cast<CLASS*>(pObject);
321 PL_DELETE(pAllocator, pPointer);
322 }
323
324private:
325 plInternal::NewInstance<void> CloneImpl(const void* pObject, plAllocator* pAllocator, plTraitInt<0>)
326 {
327 PL_REPORT_FAILURE("Clone failed since the type is not copy constructible");
328 return plInternal::NewInstance<void>(nullptr, pAllocator);
329 }
330
331 plInternal::NewInstance<void> CloneImpl(const void* pObject, plAllocator* pAllocator, plTraitInt<1>)
332 {
333 return PL_NEW(pAllocator, CLASS, *static_cast<const CLASS*>(pObject));
334 }
335};
The base class for a property that represents a function.
Definition AbstractProperty.h:535
The base class for all message handlers that a type provides.
Definition MessageHandler.h:12
This is the base interface for all properties in the reflection system. It provides enough informatio...
Definition AbstractProperty.h:150
Base class for all memory allocators.
Definition Allocator.h:23
This class encapsulates an array and it's size. It is recommended to use this class instead of plain ...
Definition ArrayPtr.h:37
Definition DynamicArray.h:81
Base class for all message types. Each message type has it's own id which is used to dispatch message...
Definition Message.h:22
Base class of all attributes can be used to decorate a RTTI property.
Definition PropertyAttributes.h:11
This class holds information about reflected types. Each instance represents one type that is known t...
Definition RTTI.h:30
PL_ALWAYS_INLINE const plRTTI * GetParentType() const
Returns the type that is the base class of this type. May be nullptr if this type has no base class.
Definition RTTI.h:54
PL_ALWAYS_INLINE bool IsDerivedFrom() const
Returns true if this type is derived from or identical to the given type.
Definition RTTI.h:70
PL_ALWAYS_INLINE const plBitflags< plTypeFlags > & GetTypeFlags() const
Returns the type flags.
Definition RTTI.h:99
PL_ALWAYS_INLINE bool CanHandleMessage() const
Returns whether this type can handle the given message type.
Definition RTTI.h:131
PL_ALWAYS_INLINE plStringView GetPluginName() const
Returns the name of the plugin which this type is declared in.
Definition RTTI.h:116
PL_ALWAYS_INLINE plUInt32 GetTypeVersion() const
Returns the version number of this type.
Definition RTTI.h:96
PL_ALWAYS_INLINE plUInt32 GetTypeSize() const
Returns the size (in bytes) of an instance of this type.
Definition RTTI.h:93
PL_ALWAYS_INLINE plRTTIAllocator * GetAllocator() const
Returns the object through which instances of this type can be allocated.
Definition RTTI.h:76
PL_ALWAYS_INLINE plStringView GetTypeName() const
Returns the name of this type.
Definition RTTI.h:48
PL_ALWAYS_INLINE plArrayPtr< const plAbstractProperty *const > GetProperties() const
Returns the array of properties that this type has. Does NOT include properties from base classes.
Definition RTTI.h:79
PL_ALWAYS_INLINE plUInt64 GetTypeNameHash() const
Returns the hash of the name of this type.
Definition RTTI.h:51
bool CanHandleMessage(plMessageId id) const
Returns whether this type can handle the message type with the given id.
Definition RTTI.h:137
PL_ALWAYS_INLINE plVariantType::Enum GetVariantType() const
Returns the corresponding variant type for this type or Invalid if there is none.
Definition RTTI.h:57
PL_ALWAYS_INLINE const plArrayPtr< plAbstractMessageHandler * > & GetMessageHandlers() const
Returns the array of message handlers that this type has.
Definition RTTI.h:119
PL_ALWAYS_INLINE bool IsDerivedFrom(const plRTTI *pBaseType) const
Returns true if this type is derived from the given type (or of the same type).
Definition RTTI.h:60
plUInt32 GetCount() const
Returns the number of active elements in the array.
Definition SmallArray_inl.h:210
Definition SmallArray.h:219
plStringView represent a read-only sub-string of a larger string, as it can store a dedicated string ...
Definition StringView.h:34
The plBitflags class allows you to work with type-safe bitflags.
Definition Bitflags.h:82
A generic delegate class which supports static functions and member functions.
Definition Delegate.h:76
Definition Allocator_inl.h:18
Definition MessageHandler.h:42
The data that is broadcast whenever a plugin is (un-) loaded.
Definition Plugin.h:11
Definition RTTI.h:164
Definition RTTI.h:150
Enum
Definition RTTI.h:154
The interface for an allocator that creates instances of reflected types.
Definition RTTI.h:234
virtual void Deallocate(void *pObject, plAllocator *pAllocator=nullptr)=0
Deallocates the given instance.
plInternal::NewInstance< T > Allocate(plAllocator *pAllocator=nullptr)
Allocates one instance.
Definition RTTI.h:242
virtual bool CanAllocate() const
Returns whether the type that is represented by this allocator, can be dynamically allocated at runti...
Definition RTTI.h:238
plInternal::NewInstance< T > Clone(const void *pObject, plAllocator *pAllocator=nullptr)
Clones the given instance.
Definition RTTI.h:249
Default implementation of plRTTIAllocator that allocates instances via the given allocator.
Definition RTTI.h:289
virtual plInternal::NewInstance< void > CloneInternal(const void *pObject, plAllocator *pAllocator) override
Clones the given instance with the given allocator.
Definition RTTI.h:302
virtual plInternal::NewInstance< void > AllocateInternal(plAllocator *pAllocator) override
Returns a new instance that was allocated with the given allocator.
Definition RTTI.h:291
virtual void Deallocate(void *pObject, plAllocator *pAllocator) override
Deletes the given instance with the given allocator.
Definition RTTI.h:313
Dummy Allocator for types that should not be allocatable through the reflection system.
Definition RTTI.h:268
virtual plInternal::NewInstance< void > AllocateInternal(plAllocator *pAllocator) override
Will trigger an assert.
Definition RTTI.h:273
virtual void Deallocate(void *pObject, plAllocator *pAllocator) override
Will trigger an assert.
Definition RTTI.h:280
virtual bool CanAllocate() const override
Returns false, because this type of allocator is used for classes that shall not be allocated dynamic...
Definition RTTI.h:270
Type traits.
Definition TypeTraits.h:12
Enum
This enum describes the type of data that is currently stored inside the variant. Note that changes t...
Definition VariantType.h:26