• R/O
  • SSH
  • HTTPS

eirrepo: Commit


Commit MetaInfo

Revision444 (tree)
Time2022-02-17 01:49:05
Authorquiret

Log Message

- added C++ RTTI helpers into DynamicTypeSystem (creation based on C++ typename/template-method, linking std::type_index to typeInfoBase, creation DTS runtime objects with custom parameters thanks to parameter packs)
- various fixes to MemoryRaw.h
- made a few adjustments to plugin struct registry flavors: added helper concept, made DTS use a direct type instead of template
- added some more relevant DTS unit tests

Change Summary

Incremental Difference

--- common/sdk/AVLTree.h (revision 443)
+++ common/sdk/AVLTree.h (revision 444)
@@ -405,7 +405,7 @@
405405 // Note that we have no more failure case because our AVL tree implementation does support adding
406406 // multiple same values.
407407 // We do allow exceptions because the comparator could throw one.
408- inline void Insert( AVLNode *node ) noexcept(noexcept(ScanForNodePosition( nullptr, *(AVLNode***)nullptr, *(AVLNode**)nullptr )))
408+ inline void Insert( AVLNode *node ) noexcept(noexcept(dispatcherType::CompareNodes( node, node )))
409409 {
410410 // Find the position to insert our new node at.
411411 AVLNode *parent;
--- common/sdk/DynamicTypeSystem.h (revision 443)
+++ common/sdk/DynamicTypeSystem.h (revision 444)
@@ -23,11 +23,17 @@
2323 #include "eirutils.h"
2424 #include "String.h"
2525 #include "MetaHelpers.h"
26+#include "AVLTree.h"
2627
2728 #include "UniChar.h"
2829
2930 #include <tuple>
3031
32+// For C++ RTTI support.
33+#include <typeinfo>
34+#include <typeindex>
35+#include <optional>
36+
3137 // Type sentry struct of the dynamic type system.
3238 // It notes the programmer that the struct has RTTI.
3339 // Every type constructed through DynamicTypeSystem has this struct before it.
@@ -88,11 +94,11 @@
8894 std::is_nothrow_destructible <structType>::value;
8995
9096 #define DTS_TEMPLARGS \
91- template <eir::StaticMemoryAllocator allocatorType, typename systemPointer, typename lockProvider_t = dtsDefaultLockProvider, template <typename genericType> typename structFlavorDispatchTypeTemplate = cachedMinimalStructRegistryFlavor, typename exceptMan = eir::DefaultExceptionManager>
97+ template <eir::StaticMemoryAllocator allocatorType, typename systemPointer, typename lockProvider_t = dtsDefaultLockProvider, PluginStructRegistryFlavor <GenericRTTI> structFlavorDispatchType = cachedMinimalStructRegistryFlavor <GenericRTTI>, typename exceptMan = eir::DefaultExceptionManager>
9298 #define DTS_TEMPLARGS_NODEF \
93- template <eir::StaticMemoryAllocator allocatorType, typename systemPointer, typename lockProvider_t, template <typename genericType> typename structFlavorDispatchTypeTemplate, typename exceptMan>
99+ template <eir::StaticMemoryAllocator allocatorType, typename systemPointer, typename lockProvider_t, PluginStructRegistryFlavor <GenericRTTI> structFlavorDispatchType, typename exceptMan>
94100 #define DTS_TEMPLUSE \
95- <allocatorType, systemPointer, lockProvider_t, structFlavorDispatchTypeTemplate, exceptMan>
101+ <allocatorType, systemPointer, lockProvider_t, structFlavorDispatchType, exceptMan>
96102
97103 // This class manages runtime type information.
98104 // It allows for dynamic C++ class extension depending on runtime conditions.
@@ -100,10 +106,6 @@
100106 DTS_TEMPLARGS
101107 struct DynamicTypeSystem
102108 {
103-private:
104- typedef structFlavorDispatchTypeTemplate <GenericRTTI> structFlavorDispatchType;
105-
106-public:
107109 static constexpr unsigned int ANONYMOUS_PLUGIN_ID = 0xFFFFFFFF;
108110
109111 // Export the system type so extensions can use it.
@@ -113,6 +115,8 @@
113115 class abstraction_construction_exception {};
114116 class type_name_conflict_exception {};
115117
118+ struct typeInfoBase;
119+
116120 private:
117121 // Lock provider for MT support.
118122 typedef typename lockProvider_t::rwlock rwlock;
@@ -119,6 +123,32 @@
119123
120124 lockProvider_t lockProvider;
121125
126+ // Lock used when using fields of the type system itself.
127+ rwlock *mainLock;
128+
129+ // List of all registered types.
130+ RwList <typeInfoBase> registeredTypes;
131+
132+ // Mapping to C++ language RTTI.
133+ struct langrtti_compare_dispatcher
134+ {
135+ static AINLINE eir::eCompResult CompareNodes( const AVLNode *left, const AVLNode *right ) noexcept
136+ {
137+ const typeInfoBase *left_ti = AVL_GETITEM( typeInfoBase, left, lang_type_node );
138+ const typeInfoBase *right_ti = AVL_GETITEM( typeInfoBase, right, lang_type_node );
139+
140+ return eir::DefaultValueCompare( left_ti->lang_type_idx.value(), right_ti->lang_type_idx.value() );
141+ }
142+
143+ static AINLINE eir::eCompResult CompareNodeWithValue( const AVLNode *left, const std::type_index& right ) noexcept
144+ {
145+ const typeInfoBase *left_ti = AVL_GETITEM( typeInfoBase, left, lang_type_node );
146+
147+ return eir::DefaultValueCompare( left_ti->lang_type_idx.value(), right );
148+ }
149+ };
150+ AVLTree <langrtti_compare_dispatcher> lang_rtti_tree;
151+
122152 public:
123153 template <typename... lockProviderArgs>
124154 requires ( eir::constructible_from <lockProvider_t, lockProviderArgs...> )
@@ -145,10 +175,9 @@
145175 public:
146176 inline DynamicTypeSystem( DynamicTypeSystem&& right ) noexcept
147177 requires ( eir::nothrow_constructible_from <lockProvider_t, lockProvider_t&&> )
148- : lockProvider( std::move( right.lockProvider ) ), registeredTypes( std::move( right.registeredTypes ) )
178+ : lockProvider( std::move( right.lockProvider ) ), mainLock( right.mainLock ), registeredTypes( std::move( right.registeredTypes ) ),
179+ lang_rtti_tree( std::move( right.lang_rtti_tree ) )
149180 {
150- this->mainLock = right.mainLock;
151-
152181 this->_update_pointers();
153182
154183 right.mainLock = nullptr;
@@ -161,6 +190,7 @@
161190 this->lockProvider = std::move( right.lockProvider );
162191 this->mainLock = right.mainLock;
163192 this->registeredTypes = std::move( right.registeredTypes );
193+ this->lang_rtti_tree = std::move( right.lang_rtti_tree );
164194
165195 this->_update_pointers();
166196
@@ -195,11 +225,6 @@
195225 Shutdown();
196226 }
197227
198-private:
199- // Lock used when using fields of the type system itself.
200- rwlock *mainLock;
201-
202-protected:
203228 struct scoped_rwlock_read
204229 {
205230 scoped_rwlock_read( const scoped_rwlock_read& ) = delete;
@@ -283,8 +308,6 @@
283308 virtual size_t GetTypeAlignment( systemPointer_t *sysPtr ) const noexcept = 0;
284309 };
285310
286- struct typeInfoBase;
287-
288311 // THREAD-SAFE, because it is an IMMUTABLE struct.
289312 struct pluginDescriptor
290313 {
@@ -310,6 +333,8 @@
310333 this->typeInfo = typeInfo;
311334 }
312335
336+ inline pluginDescriptor( const pluginDescriptor& ) = default;
337+
313338 private:
314339 // Plugin descriptors are immutable beyond construction.
315340 unsigned int pluginId;
@@ -349,19 +374,53 @@
349374
350375 private:
351376 inline typeInfoBase( void ) noexcept
352- { }
377+ {
378+ // Initialization is performed inside SetupTypeInfoBase.
379+ return;
380+ }
353381
382+ // We do not allow copies and moves.
383+ typeInfoBase( const typeInfoBase& ) = delete;
384+ typeInfoBase( typeInfoBase&& ) = delete;
385+
386+ protected:
354387 virtual ~typeInfoBase( void )
355- { }
388+ {
389+ rtti_assert( this->lang_type_idx.has_value() == false );
390+ }
356391
357- typeInfoBase( const typeInfoBase& right ) = delete;
392+ private:
393+ typeInfoBase& operator = ( const typeInfoBase& ) = delete;
394+ typeInfoBase& operator = ( typeInfoBase&& ) = delete;
358395
396+ public:
397+ // Returns true if this type must not be changed.
398+ inline bool IsImmutable( void ) const noexcept
399+ {
400+ return ( this->refCount != 0 );
401+ }
402+
403+ // Returns true if this type is not being inherited from.
404+ inline bool IsEndType( void ) const noexcept
405+ {
406+ return ( this->inheritanceCount == 0 );
407+ }
408+
409+ // Returns the static zero-terminated-string that was assigned to the type at initialization.
410+ inline const char* GetInternalName( void ) const noexcept
411+ {
412+ return this->name;
413+ }
414+
415+ protected:
359416 // Helper for the Cleanup method.
360417 typedef allocatorType typeInfoAllocatorType;
361418
419+ // Called whenever this type should be deleted.
420+ // Takes care of any destruction, even of this class itself.
362421 virtual void Cleanup( void ) noexcept = 0;
363422
364- public:
423+ private:
365424 DynamicTypeSystem *typeSys;
366425
367426 const char *name; // name of this type
@@ -370,18 +429,8 @@
370429 unsigned long refCount; // number of entities that use this type
371430
372431 // WARNING: as long as a type is referenced, it MUST not change!!!
373- inline bool IsImmutable( void ) const noexcept
374- {
375- return ( this->refCount != 0 );
376- }
377-
378432 unsigned long inheritanceCount; // number of types inheriting from this type
379433
380- inline bool IsEndType( void ) const
381- {
382- return ( this->inheritanceCount == 0 );
383- }
384-
385434 // Special properties.
386435 bool isExclusive; // can be used by the runtime to control the creation of objects.
387436 bool isAbstract; // can this type be constructed (set internally)
@@ -396,6 +445,10 @@
396445 rwlock *typeLock;
397446
398447 RwListEntry <typeInfoBase> node;
448+
449+ // C++ RTTI support.
450+ std::optional <std::type_index> lang_type_idx;
451+ AVLNode lang_type_node;
399452 };
400453
401454 AINLINE static typeInfoBase* GetTypeInfoFromTypeStruct( const GenericRTTI *rtObj ) noexcept
@@ -510,9 +563,10 @@
510563 return typeInfo->structRegistry.RegisterPlugin( pluginSize, pluginAlignment, descriptor, plugInterface );
511564 }
512565
513- // Function used to register custom plugins whose lifetime is managed by this container.
566+ // Function used to register custom plugins whose lifetime is managed by DTS itself.
514567 template <typename structTypeInterface, typename... Args>
515- requires( std::is_nothrow_destructible <structTypeInterface>::value && eir::constructible_from <structTypeInterface, Args...> )
568+ requires ( std::is_nothrow_destructible <structTypeInterface>::value && eir::constructible_from <structTypeInterface, Args...> &&
569+ std::is_base_of <pluginInterface, structTypeInterface>::value )
516570 inline pluginOffset_t RegisterCustomPlugin( size_t pluginSize, size_t pluginAlignment, const pluginDescriptor& descriptor, Args&&... constrArgs )
517571 {
518572 struct selfDestroyingInterface : public structTypeInterface
@@ -584,8 +638,6 @@
584638 return functoidHelper_t( *this ).template RegisterDependantConditionalStructPlugin <structType> ( descriptor, conditional, structSize, alignment );
585639 }
586640
587- RwList <typeInfoBase> registeredTypes;
588-
589641 private:
590642 inline void SetupTypeInfoBase( typeInfoBase *tInfo, const char *typeName, typeInterface *tInterface, typeInfoBase *inheritsFrom )
591643 {
@@ -609,8 +661,8 @@
609661 tInfo->isAbstract = false;
610662 tInfo->tInterface = tInterface;
611663 tInfo->inheritsFrom = nullptr;
612- tInfo->typeLock = lockProvider.CreateLock();
613- LIST_APPEND( registeredTypes.root, tInfo->node );
664+ tInfo->typeLock = this->lockProvider.CreateLock();
665+ LIST_APPEND( this->registeredTypes.root, tInfo->node );
614666
615667 // Set inheritance.
616668 try
@@ -634,7 +686,7 @@
634686 // Already THREAD-SAFE, because memory allocation is THREAD-SAFE and type registration is THREAD-SAFE.
635687 inline typeInfoBase* RegisterType( const char *typeName, typeInterface *typeInterface, typeInfoBase *inheritsFrom = nullptr )
636688 {
637- struct typeInfoGeneral : public typeInfoBase
689+ struct typeInfoGeneral final : public typeInfoBase
638690 {
639691 void Cleanup( void ) noexcept override
640692 {
@@ -659,21 +711,26 @@
659711 return info;
660712 }
661713
662- // Do not manually construct or destroy this class.
663714 template <typename structTypeTypeInterface>
664715 struct commonTypeInfoStruct : public typeInfoBase
665716 {
717+ friend struct DynamicTypeSystem;
718+
719+ private:
666720 template <typename... constrArgs> requires ( eir::constructible_from <structTypeTypeInterface, constrArgs...> )
667- AINLINE commonTypeInfoStruct( constrArgs&&... args ) : tInterface( std::forward <constrArgs> ( args )... )
721+ AINLINE commonTypeInfoStruct( constrArgs&&... args )
722+ : tInterface( std::forward <constrArgs> ( args )... )
668723 {
669724 return;
670725 }
671726
672- void Cleanup( void ) noexcept override
727+ protected:
728+ void Cleanup( void ) noexcept final override
673729 {
674730 eir::static_del_struct <commonTypeInfoStruct, allocatorType> ( this->typeSys, this );
675731 }
676732
733+ public:
677734 structTypeTypeInterface tInterface;
678735 };
679736
@@ -682,7 +739,13 @@
682739 requires ( eir::constructible_from <structTypeTypeInterface, constrArgs...> )
683740 inline commonTypeInfoStruct <structTypeTypeInterface>* RegisterCommonTypeInterface( const char *typeName, typeInfoBase *inheritsFrom = nullptr, constrArgs&&... args )
684741 {
685- typedef commonTypeInfoStruct <structTypeTypeInterface> typeInfoStruct;
742+ struct typeInfoStruct final : commonTypeInfoStruct <structTypeTypeInterface>
743+ {
744+ AINLINE typeInfoStruct( constrArgs&&... args ) : commonTypeInfoStruct( std::forward <constrArgs> ( args )... )
745+ {
746+ return;
747+ }
748+ };
686749
687750 typeInfoStruct *tInfo = eir::static_new_struct <typeInfoStruct, allocatorType, exceptMan> ( this, std::forward <constrArgs> ( args )... );
688751
@@ -700,6 +763,20 @@
700763 return tInfo;
701764 }
702765
766+private:
767+ template <typename langType>
768+ AINLINE void RegisterTypeToRTTI( typeInfoBase *typeInfo ) noexcept
769+ {
770+#ifdef _DEBUG
771+ rtti_assert( typeInfo->lang_type_idx.has_value() == false );
772+#endif //_DEBUG
773+
774+ typeInfo->lang_type_idx = std::type_index( typeid( langType ) );
775+
776+ this->lang_rtti_tree.Insert( &typeInfo->lang_type_node );
777+ }
778+
779+public:
703780 template <typename structType>
704781 inline typeInfoBase* RegisterAbstractType( const char *typeName, typeInfoBase *inheritsFrom = nullptr )
705782 {
@@ -758,6 +835,8 @@
758835 // WARNING: if you allow construction of types while types register themselves THIS IS A SECURITY ISSUE.
759836 // WE DO NOT DO THAT.
760837 newTypeInfo->isAbstract = true;
838+
839+ this->RegisterTypeToRTTI <structType> ( newTypeInfo );
761840 }
762841
763842 return newTypeInfo;
@@ -898,7 +977,14 @@
898977 size_t alignment;
899978 };
900979
901- return this->RegisterCommonTypeInterface <structTypeInterface> ( typeName, inheritsFrom, structSize, alignment );
980+ typeInfoBase *typeInfo = this->RegisterCommonTypeInterface <structTypeInterface> ( typeName, inheritsFrom, structSize, alignment );
981+
982+ if ( typeInfo )
983+ {
984+ this->RegisterTypeToRTTI <structType> ( typeInfo );
985+ }
986+
987+ return typeInfo;
902988 }
903989
904990 // THREAD-SAFEty cannot be guarranteed. Use with caution.
@@ -1155,6 +1241,9 @@
11551241 bool freeMetaInfo;
11561242 };
11571243
1244+ // No RTTI registration because the dynamic size and alignment of this type do not match the API usage.
1245+ // Instead there should be a special constructor-function called if you'd absolutely need it (lambda, callable struct, etc).
1246+
11581247 return this->RegisterCommonTypeInterface <structTypeInterface> ( typeName, inheritsFrom, metaInfo, freeMetaInfo );
11591248 }
11601249
@@ -1386,7 +1475,43 @@
13861475 }
13871476 }
13881477
1478+ // THREAD-SAFE, because many operations are immutable and GetTypePluginSize is called from LOCKED READ CONTEXT.
1479+ template <typename langType>
1480+ inline size_t _GetTypeStructSizeByRTTI( systemPointer_t *sysPtr, typeInfoBase *typeInfo, size_t& alignmentOut ) const
1481+ {
1482+ // Attempt to get the memory the language object will take.
1483+ size_t baseStructSize = sizeof( langType );
1484+ size_t baseStructAlignment = alignof( langType );
1485+
1486+ // Adjust that objMemSize so we can store meta information + plugins.
1487+ size_t objMemSize = ALIGN_SIZE( sizeof( GenericRTTI ), baseStructAlignment );
1488+
1489+ objMemSize += baseStructSize;
1490+
1491+ scoped_rwlock_read typeLock( this->lockProvider, typeInfo->typeLock );
1492+
1493+ // Calculate the memory that is required by all plugin structs.
1494+ size_t pluginAlignment;
1495+ AdvanceTypePluginSize( typeInfo, objMemSize, pluginAlignment );
1496+
1497+ // Return the proper alignment.
1498+ alignmentOut = std::max( std::max( alignof(GenericRTTI), baseStructAlignment ), pluginAlignment );
1499+
1500+ return objMemSize;
1501+ }
1502+
13891503 public:
1504+ template <typename langType>
1505+ inline size_t GetTypeStructSizeByRTTI( systemPointer_t *sysPtr, size_t& alignmentOut ) const
1506+ {
1507+ typeInfoBase *typeInfo = this->FindTypeInfoByRTTI <langType> ();
1508+
1509+ if ( typeInfo == nullptr )
1510+ return 0;
1511+
1512+ return this->_GetTypeStructSizeByRTTI <langType> ( sysPtr, typeInfo, alignmentOut );
1513+ }
1514+
13901515 // THREAD-SAFE, because many operations are immutable and GetTypePluginSize is called from LOCKED READ CONTEXT.
13911516 inline size_t GetTypeStructSize( systemPointer_t *sysPtr, typeInfoBase *typeInfo, void *construct_params, size_t& alignmentOut ) const
13921517 {
@@ -1521,8 +1646,21 @@
15211646 return (void*)SCALE_DOWN( (size_t)objMem, align_alloc );
15221647 }
15231648
1649+ template <typename langType>
1650+ inline typeInfoBase* FindTypeInfoByRTTI( void ) noexcept
1651+ {
1652+ std::type_index tidx = typeid( langType );
1653+
1654+ AVLNode *findNode = this->lang_rtti_tree.FindNode( tidx );
1655+
1656+ if ( findNode == nullptr )
1657+ return nullptr;
1658+
1659+ return AVL_GETITEM( typeInfoBase, findNode, lang_type_node );
1660+ }
1661+
15241662 public:
1525- // Returns the runtime information object that will be allocated at objMem.
1663+ // Returns the runtime object that will be allocated at objMem.
15261664 // The returned pointer is not necessaringly equal to objMem itself if alignment is skewed.
15271665 // THREAD-SAFE, because the typeInterface is THREAD-SAFE and plugin construction is THREAD-SAFE.
15281666 inline GenericRTTI* ConstructPlacement( systemPointer_t *sysPtr, void *allocMem, typeInfoBase *typeInfo, void *construct_params )
@@ -1591,11 +1729,12 @@
15911729 return objOut;
15921730 }
15931731
1732+ // Constructs a runtime object in allocated memory.
15941733 // THREAD-SAFE, because memory allocation is THREAD-SAFE, GetTypeStructSize is THREAD-SAFE and ConstructPlacement is THREAD-SAFE.
15951734 inline GenericRTTI* Construct( systemPointer_t *sysPtr, typeInfoBase *typeInfo, void *construct_params )
15961735 {
15971736 #ifdef _DEBUG
1598- assert( typeInfo->typeSys == this );
1737+ rtti_assert( typeInfo->typeSys == this );
15991738 #endif //_DEBUG
16001739
16011740 GenericRTTI *objOut = nullptr;
@@ -1650,7 +1789,7 @@
16501789 return objOut;
16511790 }
16521791
1653- // Constructs an object at the the provided allocMem, using any copy-constructor.
1792+ // Constructs a copy of the provided runtime object at the provided allocMem, using any copy-constructor.
16541793 // THREAD-SAFE, because many operations are IMMUTABLE, the type interface is THREAD-SAFE, plugin construction
16551794 // is called from LOCKED READ CONTEXT and plugin assignment is called from LOCKED READ CONTEXT.
16561795 inline GenericRTTI* ClonePlacement( systemPointer_t *sysPtr, void *allocMem, const GenericRTTI *toBeCloned )
@@ -1689,7 +1828,7 @@
16891828
16901829 try
16911830 {
1692- // Attempt to copy construct the language part.
1831+ // Attempt to copy-construct the language part.
16931832 tInterface->CopyConstruct( objMem, srcObjStruct );
16941833 }
16951834 catch( ... )
@@ -1752,8 +1891,9 @@
17521891 return objOut;
17531892 }
17541893
1894+ // Constructs a copy of the provided runtime object in allocated memory, using any copy-constructor.
17551895 // THREAD-SAFE, because GetTypeStructSize is THREAD-SAFE, memory allocation is THREAD-SAFE
1756- // and ClonePlacement is THREAD_SAFE.
1896+ // and ClonePlacement is THREAD-SAFE.
17571897 inline GenericRTTI* Clone( systemPointer_t *sysPtr, const GenericRTTI *toBeCloned )
17581898 {
17591899 DebugRTTIStruct( toBeCloned );
@@ -1785,7 +1925,7 @@
17851925 return objOut;
17861926 }
17871927
1788- // Constructs an object at the given allocMem location, using any move-constructor.
1928+ // Constructs a runtime object at the given allocMem location, using any move-constructor.
17891929 // THREAD-SAFE, because many operations are IMMUTABLE, the type interface is THREAD-SAFE, plugin construction
17901930 // is called from LOCKED READ CONTEXT and plugin assignment is called from LOCKED READ CONTEXT.
17911931 inline GenericRTTI* MovePlacement( systemPointer_t *sysPtr, void *allocMem, GenericRTTI *toBeMoved )
@@ -1824,7 +1964,7 @@
18241964
18251965 try
18261966 {
1827- // Attempt to move construct the language part.
1967+ // Attempt to move-construct the language part.
18281968 tInterface->MoveConstruct( objMem, srcObjStruct );
18291969 }
18301970 catch( ... )
@@ -1887,6 +2027,149 @@
18872027 return objOut;
18882028 }
18892029
2030+ // *** RTTI CONSTRUCTION INTERFACE BEGIN
2031+
2032+private:
2033+ template <typename langType, typename... constrArgs> requires ( eir::constructible_from <langType, constrArgs...> )
2034+ inline langType* _ConstructPlacementByRTTI( typeInfoBase *typeInfo, systemPointer_t *sysPtr, void *allocMem, constrArgs&&... cargs )
2035+ {
2036+ langType *objOut = nullptr;
2037+ {
2038+ // Reference the type info.
2039+ ReferenceTypeInfo( typeInfo );
2040+
2041+ // Get the specialization interface.
2042+ typeInterface *tInterface = typeInfo->tInterface;
2043+
2044+ // Get a pointer to GenericRTTI and the object memory.
2045+ size_t baseStructAlignment = tInterface->GetTypeAlignment( sysPtr );
2046+
2047+ void *objMem = GetObjectMemoryFromAllocation( allocMem, baseStructAlignment );
2048+
2049+ GenericRTTI *objTypeMeta = GetTypeStructFromObject( objMem );
2050+
2051+ // Initialize the RTTI struct.
2052+ objTypeMeta->type_meta = typeInfo;
2053+#ifdef _DEBUG
2054+ objTypeMeta->typesys_ptr = this;
2055+#endif //_DEBUG
2056+
2057+ // Initialize the language object.
2058+ langType *tmpObj;
2059+
2060+ try
2061+ {
2062+ // Attempt to construct the language part.
2063+ tmpObj = new (objMem) langType( std::forward <constrArgs> ( cargs )... );
2064+ }
2065+ catch( ... )
2066+ {
2067+ // We failed to construct the object struct, so it is invalid.
2068+ tmpObj = nullptr;
2069+ }
2070+
2071+ if ( tmpObj )
2072+ {
2073+ // Only proceed if we have successfully constructed the object struct.
2074+ // Now construct the plugins.
2075+ bool pluginConstructSuccess = ConstructPlugins( sysPtr, typeInfo, objTypeMeta );
2076+
2077+ if ( pluginConstructSuccess )
2078+ {
2079+ // We are finished! Return the new language object.
2080+ objOut = tmpObj;
2081+ }
2082+ else
2083+ {
2084+ // We failed, so destruct the class again.
2085+ tInterface->Destruct( objMem );
2086+ }
2087+ }
2088+
2089+ if ( objOut == nullptr )
2090+ {
2091+ // Since we did not return a proper object, dereference again.
2092+ DereferenceTypeInfo( typeInfo );
2093+ }
2094+ }
2095+ return objOut;
2096+ }
2097+
2098+public:
2099+ // Constructs a runtime object from the provided arguments at the specified memory location.
2100+ // Copy or move construction does not automatically invoke the DTS plugin data assignment interface.
2101+ // Objects should be destroyed by using the DTS DestroyPlacement method.
2102+ template <typename langType, typename... constrArgs> requires ( eir::constructible_from <langType, constrArgs...> )
2103+ inline langType* ConstructPlacementByRTTI( systemPointer_t *sysPtr, void *objMem, constrArgs&&... cargs )
2104+ {
2105+ typeInfoBase *typeInfo = this->FindTypeInfoByRTTI <langType> ();
2106+
2107+ if ( typeInfo == nullptr )
2108+ return nullptr;
2109+
2110+ return this->_ConstructPlacementByRTTI( typeInfo, sysPtr, objMem, std::forward <constrArgs> ( cargs )... );
2111+ }
2112+
2113+ // Constructs a runtime object from the provided arguments in allocator memory.
2114+ // Objects should be destroyed by using the DTS Destroy method.
2115+ template <typename langType, typename... constrArgs> requires ( eir::constructible_from <langType, constrArgs...> )
2116+ inline langType* ConstructByRTTI( systemPointer_t *sysPtr, constrArgs&&... cargs )
2117+ {
2118+ typeInfoBase *typeInfo = this->FindTypeInfoByRTTI <langType> ();
2119+
2120+ langType *objOut = nullptr;
2121+
2122+ if ( typeInfo != nullptr )
2123+ {
2124+ // We must reference the type info to prevent the issue where the type struct can change
2125+ // during construction.
2126+ ReferenceTypeInfo( typeInfo );
2127+
2128+ try
2129+ {
2130+ size_t objMemAlignment;
2131+ size_t objMemSize = this->_GetTypeStructSizeByRTTI <langType> ( sysPtr, typeInfo, objMemAlignment );
2132+
2133+ void *allocMem = allocatorType::Allocate( this, objMemSize, objMemAlignment );
2134+
2135+ if ( allocMem )
2136+ {
2137+ try
2138+ {
2139+ // Attempt to construct the object on the memory.
2140+ objOut = this->_ConstructPlacementByRTTI <langType> ( typeInfo, sysPtr, allocMem, std::forward <constrArgs> ( cargs )... );
2141+ }
2142+ catch( ... )
2143+ {
2144+ // Just to be on the safe side.
2145+ allocatorType::Free( this, allocMem );
2146+
2147+ throw;
2148+ }
2149+
2150+ if ( !objOut )
2151+ {
2152+ // Deallocate the memory again, as we seem to have failed.
2153+ allocatorType::Free( this, allocMem );
2154+ }
2155+ }
2156+ }
2157+ catch( ... )
2158+ {
2159+ // Just to be on the safe side.
2160+ DereferenceTypeInfo( typeInfo );
2161+
2162+ throw;
2163+ }
2164+
2165+ // We can dereference the type info again.
2166+ DereferenceTypeInfo( typeInfo );
2167+ }
2168+ return objOut;
2169+ }
2170+
2171+ // *** RTTI CONSTRUCTION INTERFACE END
2172+
18902173 // THREAD-SAFE, because single atomic operation.
18912174 inline void SetTypeInfoExclusive( typeInfoBase *typeInfo, bool isExclusive ) noexcept
18922175 {
@@ -1909,7 +2192,7 @@
19092192 inline void SetTypeInfoInheritingClass( typeInfoBase *subClass, typeInfoBase *inheritedClass, bool requiresSystemLock = true )
19102193 {
19112194 #ifdef _DEBUG
1912- assert( subClass->typeSys == this );
2195+ rtti_assert( subClass->typeSys == this );
19132196 #endif //_DEBUG
19142197
19152198 bool subClassImmutability = subClass->IsImmutable();
@@ -1927,7 +2210,7 @@
19272210 if ( inheritedClass != nullptr )
19282211 {
19292212 #ifdef _DEBUG
1930- assert( inheritedClass->typeSys == this );
2213+ rtti_assert( inheritedClass->typeSys == this );
19312214 #endif //_DEBUG
19322215
19332216 typeInfoBase *alreadyExisting = FindTypeInfoNolock( subClass->name, inheritedClass );
@@ -1997,8 +2280,8 @@
19972280 inline bool IsTypeInheritingFrom( typeInfoBase *baseClass, typeInfoBase *subClass ) const
19982281 {
19992282 #ifdef _DEBUG
2000- assert( baseClass->typeSys == this );
2001- assert( subClass->typeSys == this );
2283+ rtti_assert( baseClass->typeSys == this );
2284+ rtti_assert( subClass->typeSys == this );
20022285 #endif //_DEBUG
20032286
20042287 // We do not have to lock on this, because equality is an IMMUTABLE property of types.
@@ -2136,7 +2419,7 @@
21362419 inline void DeleteType( typeInfoBase *typeInfo )
21372420 {
21382421 #ifdef _DEBUG
2139- assert( typeInfo->typeSys == this );
2422+ rtti_assert( typeInfo->typeSys == this );
21402423 #endif //_DEBUG
21412424
21422425 // Make sure we do not inherit from anything anymore.
@@ -2183,6 +2466,14 @@
21832466 LIST_REMOVE( typeInfo->node );
21842467 }
21852468
2469+ // If the type is registered under C++ RTTI, then remove it from that list.
2470+ if ( typeInfo->lang_type_idx.has_value() )
2471+ {
2472+ this->lang_rtti_tree.RemoveByNodeFast( &typeInfo->lang_type_node );
2473+
2474+ typeInfo->lang_type_idx.reset();
2475+ }
2476+
21862477 typeInfo->Cleanup();
21872478 }
21882479
--- common/sdk/MemoryRaw.h (revision 443)
+++ common/sdk/MemoryRaw.h (revision 444)
@@ -32,7 +32,7 @@
3232 // EXAMPLE: ALIGN( 0x1001, 4, 4 ) -> 0x1004 (equivalent of compiler structure padding alignment)
3333 // ALIGN( 0x1003, 1, 4 ) -> 0x1000
3434 // ALIGN( 0x1003, 2, 4 ) -> 0x1004
35-template <typename numberType> requires ( std::is_unsigned <numberType>::value )
35+template <typename numberType> requires ( std::is_integral <numberType>::value && std::is_unsigned <numberType>::value )
3636 AINLINE numberType _ALIGN_GP( numberType num, numberType sector, numberType align )
3737 {
3838 // General purpose alignment routine.
@@ -42,7 +42,7 @@
4242 return sectorOffset - ( sectorOffset % align );
4343 }
4444
45-template <typename numberType> requires ( std::is_unsigned <numberType>::value )
45+template <typename numberType> requires ( std::is_integral <numberType>::value && std::is_unsigned <numberType>::value )
4646 AINLINE numberType _ALIGN_NATIVE( numberType num, numberType sector, numberType align )
4747 {
4848 // assume math based on x86 bits.
@@ -57,7 +57,7 @@
5757 }
5858 }
5959
60-template <typename numberType> requires ( std::is_unsigned <numberType>::value )
60+template <typename numberType> requires ( std::is_integral <numberType>::value && std::is_unsigned <numberType>::value )
6161 AINLINE numberType ALIGN( numberType num, numberType sector, numberType align )
6262 {
6363 if constexpr ( std::same_as <numberType, unsigned char> ||
@@ -74,7 +74,7 @@
7474 }
7575
7676 // Helper macro (equivalent of EXAMPLE 1)
77-template <typename numberType> requires ( std::is_unsigned <numberType>::value )
77+template <typename numberType> requires ( std::is_integral <numberType>::value && std::is_unsigned <numberType>::value )
7878 inline numberType ALIGN_SIZE( numberType num, numberType sector )
7979 {
8080 return ( ALIGN( (num), (sector), (sector) ) );
@@ -81,7 +81,7 @@
8181 }
8282
8383 // Aligning things to the boundary below.
84-template <typename numberType> requires ( std::is_unsigned <numberType>::value )
84+template <typename numberType> requires ( std::is_integral <numberType>::value && std::is_unsigned <numberType>::value )
8585 AINLINE numberType SCALE_DOWN( numberType value, numberType modval ) noexcept
8686 {
8787 // This is faster than divide-and-multiply, plus it does exactly the same.
--- common/sdk/MemoryUtils.h (revision 443)
+++ common/sdk/MemoryUtils.h (revision 444)
@@ -225,7 +225,7 @@
225225 return true;
226226 }
227227
228- static AINLINE numberType GetSpanSize( managerType& manager, numberType startSpanSize = 0 )
228+ static AINLINE numberType GetSpanSize( const managerType& manager, numberType startSpanSize = 0 )
229229 {
230230 numberType theSpanSize = std::move( startSpanSize );
231231
@@ -691,7 +691,7 @@
691691 return ( *GetManager()->blockList.root.prev );
692692 }
693693
694- AINLINE bool HasMemoryBlocks( void )
694+ AINLINE bool HasMemoryBlocks( void ) const
695695 {
696696 return ( LIST_EMPTY( GetManager()->blockList.root ) == false );
697697 }
@@ -757,7 +757,7 @@
757757 LIST_CLEAR( blockList.root );
758758 }
759759
760- inline numberType GetSpanSize( void )
760+ inline numberType GetSpanSize( void ) const
761761 {
762762 return allocSemantics::GetSpanSize( allocSemMan );
763763 }
--- common/sdk/PluginFactory.h (revision 443)
+++ common/sdk/PluginFactory.h (revision 444)
@@ -32,7 +32,7 @@
3232
3333 // Class used to register anonymous structs that can be placed on top of a C++ type.
3434 #define APSR_TEMPLARGS \
35- template <typename abstractionType, typename pluginDescriptorType_meta, typename pluginAvailabilityDispatchType, eir::MemoryAllocator allocatorType, typename... AdditionalArgs>
35+ template <typename abstractionType, typename pluginDescriptorType_meta, PluginStructRegistryFlavor <abstractionType> pluginAvailabilityDispatchType, eir::MemoryAllocator allocatorType, typename... AdditionalArgs>
3636 #define APSR_TEMPLUSE \
3737 <abstractionType, pluginDescriptorType_meta, pluginAvailabilityDispatchType, allocatorType, AdditionalArgs...>
3838
@@ -770,9 +770,9 @@
770770 // This container is NOT MULTI-THREAD SAFE.
771771 // All operations are expected to be ATOMIC.
772772 #define SPCF_TEMPLARGS \
773- template <SPCFClassType classType, eir::MemoryAllocator allocatorType, typename exceptMan = eir::DefaultExceptionManager, typename flavorType = cachedMinimalStructRegistryFlavor <classType>, typename... constrArgs>
773+ template <SPCFClassType classType, eir::MemoryAllocator allocatorType, typename exceptMan = eir::DefaultExceptionManager, PluginStructRegistryFlavor <classType> flavorType = cachedMinimalStructRegistryFlavor <classType>, typename... constrArgs>
774774 #define SPCF_TEMPLARGS_NODEF \
775- template <SPCFClassType classType, eir::MemoryAllocator allocatorType, typename exceptMan, typename flavorType, typename... constrArgs>
775+ template <SPCFClassType classType, eir::MemoryAllocator allocatorType, typename exceptMan, PluginStructRegistryFlavor <classType> flavorType, typename... constrArgs>
776776 #define SPCF_TEMPLUSE \
777777 <classType, allocatorType, exceptMan, flavorType, constrArgs...>
778778
--- common/sdk/PluginFlavors.h (revision 443)
+++ common/sdk/PluginFlavors.h (revision 444)
@@ -13,47 +13,61 @@
1313 #ifndef _EIR_PLUGIN_FACTORY_FLAVORS_HEADER_
1414 #define _EIR_PLUGIN_FACTORY_FLAVORS_HEADER_
1515
16+#include "eirutils.h"
17+
18+#include <type_traits>
19+
20+template <typename flavorType, typename abstractionType>
21+concept PluginStructRegistryFlavor =
22+ eir::constructible_from <flavorType> &&
23+ requires ( flavorType FT, size_t& S_OUT, const abstractionType *ATPTR, const void *MNGPTR ) {
24+ { FT.GetPluginStructOffset( MNGPTR, size_t(), S_OUT ) } -> std::same_as <bool>;
25+ { FT.GetPluginStructOffsetByObject( MNGPTR, ATPTR, size_t(), S_OUT ) } -> std::same_as <bool>;
26+ { FT.GetPluginAllocSize( MNGPTR ) } -> std::same_as <size_t>;
27+ { FT.GetPluginAllocSizeByObject( MNGPTR, ATPTR ) } -> std::same_as <size_t>;
28+ FT.UpdatePluginRegion( MNGPTR );
29+ typename decltype(FT)::template pluginInterfaceBase <void>;
30+ typename decltype(FT)::template regionIterator <void>;
31+ } &&
32+ std::is_invocable_r <bool, decltype(flavorType::DoesUseUnifiedPluginOffset)>::value;
33+
1634 // Struct registry flavor is used to fine-tune the performance of said registry by extending it with features.
1735 // The idea is that we maximize performance by only giving it the features you really want it to have.
18-template <typename abstractionType>
36+template <typename abstractionType, typename... pluginInterfaceBases> requires ( std::is_fundamental <pluginInterfaceBases>::value && ... )
1937 struct cachedMinimalStructRegistryFlavor
2038 {
2139 size_t pluginAllocSize;
2240
23- cachedMinimalStructRegistryFlavor( void )
41+ cachedMinimalStructRegistryFlavor( void ) noexcept
2442 {
2543 // Reset to zero as we have no plugins allocated.
2644 this->pluginAllocSize = 0;
2745 }
2846
29- template <typename managerType>
30- inline bool GetPluginStructOffset( managerType *manPtr, size_t handleOffset, size_t& actualOffset ) const
47+ inline bool GetPluginStructOffset( const void *_, size_t handleOffset, size_t& actualOffset ) const
3148 {
3249 actualOffset = handleOffset;
3350 return true;
3451 }
3552
36- template <typename managerType>
37- inline bool GetPluginStructOffsetByObject( managerType *manPtr, const abstractionType *object, size_t handleOffset, size_t& actualOffset ) const
53+ inline bool GetPluginStructOffsetByObject( const void *_, const abstractionType *object, size_t handleOffset, size_t& actualOffset ) const
3854 {
3955 actualOffset = handleOffset;
4056 return true;
4157 }
4258
43- template <typename managerType>
44- inline size_t GetPluginAllocSize( managerType *manPtr ) const
59+ inline size_t GetPluginAllocSize( const void *_ ) const
4560 {
4661 return this->pluginAllocSize;
4762 }
4863
49- template <typename managerType>
50- inline size_t GetPluginAllocSizeByObject( managerType *manPtr, const abstractionType *object ) const
64+ inline size_t GetPluginAllocSizeByObject( const void *_, const abstractionType *object ) const
5165 {
5266 return this->pluginAllocSize;
5367 }
5468
5569 template <typename managerType>
56- inline void UpdatePluginRegion( managerType *manPtr )
70+ inline void UpdatePluginRegion( const managerType *manPtr )
5771 {
5872 // Update the overall class size.
5973 // It is determined by the end of this plugin struct.
@@ -66,7 +80,7 @@
6680 }
6781
6882 template <typename managerType>
69- struct pluginInterfaceBase
83+ struct pluginInterfaceBase : public pluginInterfaceBases...
7084 {
7185 // Nothing really.
7286 };
@@ -144,6 +158,7 @@
144158 }
145159 };
146160 };
161+static_assert( PluginStructRegistryFlavor <cachedMinimalStructRegistryFlavor <void>, void> == true );
147162
148163 template <typename pluginInterfaceBaseType, typename abstractionType, typename pluginDescriptorType>
149164 concept PluginFlavorConditionalPluginInterface =
@@ -153,7 +168,7 @@
153168 template <typename abstractionType>
154169 struct conditionalStructRegistryFlavor
155170 {
156- conditionalStructRegistryFlavor( void )
171+ conditionalStructRegistryFlavor( void ) noexcept
157172 {
158173 return;
159174 }
@@ -364,5 +379,6 @@
364379 }
365380 };
366381 };
382+static_assert( PluginStructRegistryFlavor <conditionalStructRegistryFlavor <void>, void> == true );
367383
368384 #endif //_EIR_PLUGIN_FACTORY_FLAVORS_HEADER_
\ No newline at end of file
--- unittests/src/dynamictypesystem.cond.cpp (revision 443)
+++ unittests/src/dynamictypesystem.cond.cpp (revision 444)
@@ -8,7 +8,7 @@
88
99 DEFINE_HEAP_REDIR_ALLOC_IMPL( condDTSHeapAllocator );
1010
11-typedef DynamicTypeSystem <condDTSHeapAllocator, void, dtsDefaultLockProvider, conditionalStructRegistryFlavor> condTypeSystem_t;
11+typedef DynamicTypeSystem <condDTSHeapAllocator, void, dtsDefaultLockProvider, conditionalStructRegistryFlavor <GenericRTTI>> condTypeSystem_t;
1212
1313 struct dtsCondStruct
1414 {
@@ -81,7 +81,7 @@
8181 {
8282 condTypeSystem_t::typeInfoBase *typeInfo = condTypeSystem_t::GetTypeInfoFromTypeStruct( rtObj );
8383
84- if ( strcmp( typeInfo->name, "test_type" ) == 0 )
84+ if ( strcmp( typeInfo->GetInternalName(), "test_type" ) == 0 )
8585 {
8686 const my_test_type *theType = (const my_test_type*)condTypeSystem_t::GetConstObjectFromTypeStruct( rtObj, alignof(my_test_type) );
8787
--- unittests/src/dynamictypesystem.cpp (revision 443)
+++ unittests/src/dynamictypesystem.cpp (revision 444)
@@ -647,4 +647,47 @@
647647 assert( dts.MakeTypeInfoFullName <CRTHeapAllocator> ( type ) == "int" );
648648 }
649649 printf( "ok.\n" );
650+
651+ printf( "testing DTS ConstructByRTTI (simple construction)..." );
652+ {
653+ DynamicTypeSystem <CRTHeapAllocator, void> dts;
654+
655+ dts.RegisterStructType <testObject> ( "testObject" );
656+
657+ testObject *obj = dts.ConstructByRTTI <testObject> ( nullptr, nullptr, nullptr );
658+
659+ assert( obj != nullptr );
660+
661+ GenericRTTI *rtObj = decltype(dts)::GetTypeStructFromObject( obj );
662+
663+ dts.Destroy( nullptr, rtObj );
664+ }
665+ printf( "ok.\n" );
666+
667+ printf( "testing DTS ConstructByRTTI (generic cloning)..." );
668+ {
669+ DynamicTypeSystem <CRTHeapAllocator, void> dts;
670+
671+ dts.RegisterStructType <testObject> ( "testObject" );
672+
673+ testObject *obj = dts.ConstructByRTTI <testObject> ( nullptr, nullptr, nullptr );
674+
675+ assert( obj != nullptr );
676+
677+ GenericRTTI *rtObj = decltype(dts)::GetTypeStructFromObject( obj );
678+
679+ GenericRTTI *cloned = dts.Clone( nullptr, rtObj );
680+
681+ assert( cloned != nullptr );
682+
683+ dts.Destroy( nullptr, rtObj );
684+ dts.Destroy( nullptr, cloned );
685+ }
686+ printf( "ok.\n" );
687+
688+ printf( "testing DTS custom calculation method plugin..." );
689+ {
690+ // TODO.
691+ }
692+ printf( "ok.\n" );
650693 }
Show on old repository browser