• R/O
  • SSH
  • HTTPS

eirrepo: Commit


Commit MetaInfo

Revision448 (tree)
Time2022-02-21 04:58:27
Authorquiret

Log Message

- added DynamicTypeSystem::RepurposeByRTTI method: internalize objects into the type-system out of previously constructed language objects + unit tests
- added object-allocator support for DTS

Change Summary

Incremental Difference

--- common/sdk/DynamicTypeSystem.h (revision 447)
+++ common/sdk/DynamicTypeSystem.h (revision 448)
@@ -94,9 +94,9 @@
9494 std::is_nothrow_destructible <structType>::value;
9595
9696 #define DTS_TEMPLARGS \
97- template <eir::StaticMemoryAllocator allocatorType, typename systemPointer, typename lockProvider_t = dtsDefaultLockProvider, PluginStructRegistryFlavor <GenericRTTI> structFlavorDispatchType = cachedMinimalStructRegistryFlavor <GenericRTTI>, typename exceptMan = eir::DefaultExceptionManager>
97+ template <eir::MemoryAllocator allocatorType, typename systemPointer, typename lockProvider_t = dtsDefaultLockProvider, PluginStructRegistryFlavor <GenericRTTI> structFlavorDispatchType = cachedMinimalStructRegistryFlavor <GenericRTTI>, typename exceptMan = eir::DefaultExceptionManager>
9898 #define DTS_TEMPLARGS_NODEF \
99- template <eir::StaticMemoryAllocator allocatorType, typename systemPointer, typename lockProvider_t, PluginStructRegistryFlavor <GenericRTTI> structFlavorDispatchType, typename exceptMan>
99+ template <eir::MemoryAllocator allocatorType, typename systemPointer, typename lockProvider_t, PluginStructRegistryFlavor <GenericRTTI> structFlavorDispatchType, typename exceptMan>
100100 #define DTS_TEMPLUSE \
101101 <allocatorType, systemPointer, lockProvider_t, structFlavorDispatchType, exceptMan>
102102
@@ -118,10 +118,12 @@
118118 struct typeInfoBase;
119119
120120 private:
121+ [[no_unique_address]] allocatorType allocMan;
122+
121123 // Lock provider for MT support.
122124 typedef typename lockProvider_t::rwlock rwlock;
123125
124- lockProvider_t lockProvider;
126+ [[no_unique_address]] lockProvider_t lockProvider;
125127
126128 // Lock used when using fields of the type system itself.
127129 rwlock *mainLock;
@@ -150,18 +152,26 @@
150152 AVLTree <langrtti_compare_dispatcher> lang_rtti_tree;
151153
152154 public:
153- template <typename... lockProviderArgs>
154- requires ( eir::constructible_from <lockProvider_t, lockProviderArgs...> )
155- inline DynamicTypeSystem( std::tuple <lockProviderArgs...>&& lpArgs ) noexcept(eir::nothrow_constructible_from <lockProvider_t, lockProviderArgs...>)
156- : lockProvider( std::make_from_tuple <lockProvider_t> ( lpArgs ) )
155+ template <typename... lockProviderArgs, typename... allocArgs>
156+ requires ( eir::constructible_from <lockProvider_t, lockProviderArgs...> && eir::constructible_from <allocatorType, allocArgs...> )
157+ inline DynamicTypeSystem( std::tuple <lockProviderArgs...>&& lpArgs, std::tuple <allocArgs...>&& a_args = std::tuple() )
158+ noexcept(eir::nothrow_constructible_from <lockProvider_t, lockProviderArgs...> && eir::nothrow_constructible_from <allocatorType, allocArgs...>)
159+ : lockProvider( std::make_from_tuple <lockProvider_t> ( std::move( lpArgs ) ) ), allocMan( std::make_from_tuple <allocatorType> ( std::move( a_args ) ) )
157160 {
158161 this->mainLock = this->lockProvider.CreateLock();
159162 }
160- inline DynamicTypeSystem( void ) noexcept requires ( eir::nothrow_constructible_from <lockProvider_t> )
161- : DynamicTypeSystem( std::tuple() )
163+ inline DynamicTypeSystem( void ) noexcept requires ( eir::nothrow_constructible_from <lockProvider_t> && eir::nothrow_constructible_from <allocatorType> )
164+ : DynamicTypeSystem( std::tuple(), std::tuple() )
162165 {
163166 return;
164167 }
168+ template <typename... allocArgs>
169+ requires ( eir::nothrow_constructible_from <lockProvider_t> && eir::constructible_from <allocatorType, allocArgs...> )
170+ inline DynamicTypeSystem( eir::constr_with_alloc _, allocArgs&&... a_args )
171+ : DynamicTypeSystem( std::tuple(), std::tuple <allocArgs&&...> ( std::forward <allocArgs> ( a_args )... ) )
172+ {
173+ return;
174+ }
165175 inline DynamicTypeSystem( const DynamicTypeSystem& ) = delete;
166176
167177 private:
@@ -591,13 +601,15 @@
591601
592602 void DeleteOnUnregister( void ) noexcept override
593603 {
594- eir::static_del_struct <selfDestroyingInterface, allocatorType> ( this->typeSys, this );
604+ DynamicTypeSystem *typeSys = this->typeSys;
605+
606+ eir::dyn_del_struct <selfDestroyingInterface> ( typeSys->allocMan, typeSys, this );
595607 }
596608
597609 DynamicTypeSystem *typeSys;
598610 };
599611
600- selfDestroyingInterface *pluginInfo = eir::static_new_struct <selfDestroyingInterface, allocatorType, exceptMan> ( this, this, std::forward <Args> ( constrArgs )... );
612+ selfDestroyingInterface *pluginInfo = eir::dyn_new_struct <selfDestroyingInterface, exceptMan> ( this->allocMan, this, this, std::forward <Args> ( constrArgs )... );
601613
602614 try
603615 {
@@ -605,7 +617,7 @@
605617 }
606618 catch( ... )
607619 {
608- eir::static_del_struct <selfDestroyingInterface, allocatorType> ( this, pluginInfo );
620+ eir::dyn_del_struct <selfDestroyingInterface> ( this->allocMan, this, pluginInfo );
609621
610622 throw;
611623 }
@@ -703,12 +715,14 @@
703715 {
704716 void Cleanup( void ) noexcept override
705717 {
718+ DynamicTypeSystem *typeSys = this->typeSys;
719+
706720 // Terminate ourselves.
707- eir::static_del_struct <typeInfoGeneral, allocatorType> ( this->typeSys, this );
721+ eir::dyn_del_struct <typeInfoGeneral> ( typeSys->allocMan, typeSys, this );
708722 }
709723 };
710724
711- typeInfoGeneral *info = eir::static_new_struct <typeInfoGeneral, allocatorType, exceptMan> ( this );
725+ typeInfoGeneral *info = eir::dyn_new_struct <typeInfoGeneral, exceptMan> ( this->allocMan, this );
712726
713727 try
714728 {
@@ -716,7 +730,7 @@
716730 }
717731 catch( ... )
718732 {
719- eir::static_del_struct <typeInfoGeneral, allocatorType> ( this, info );
733+ eir::dyn_del_struct <typeInfoGeneral> ( this->allocMan, this, info );
720734
721735 throw;
722736 }
@@ -740,7 +754,9 @@
740754 protected:
741755 void Cleanup( void ) noexcept final override
742756 {
743- eir::static_del_struct <commonTypeInfoStruct, allocatorType> ( this->typeSys, this );
757+ DynamicTypeSystem *typeSys = this->typeSys;
758+
759+ eir::dyn_del_struct <commonTypeInfoStruct> ( typeSys->allocMan, typeSys, this );
744760 }
745761
746762 public:
@@ -760,7 +776,7 @@
760776 }
761777 };
762778
763- typeInfoStruct *tInfo = eir::static_new_struct <typeInfoStruct, allocatorType, exceptMan> ( this, std::forward <constrArgs> ( args )... );
779+ typeInfoStruct *tInfo = eir::dyn_new_struct <typeInfoStruct, exceptMan> ( this->allocMan, this, std::forward <constrArgs> ( args )... );
764780
765781 try
766782 {
@@ -768,7 +784,7 @@
768784 }
769785 catch( ... )
770786 {
771- eir::static_del_struct <typeInfoStruct, allocatorType> ( this, tInfo );
787+ eir::dyn_del_struct <typeInfoStruct> ( this->allocMan, this, tInfo );
772788
773789 throw;
774790 }
@@ -1129,7 +1145,9 @@
11291145
11301146 void DeleteOnUnregister( void ) noexcept override
11311147 {
1132- eir::static_del_struct <structPluginInterface, allocatorType> ( this->typeSys, this );
1148+ DynamicTypeSystem *typeSys = this->typeSys;
1149+
1150+ eir::dyn_del_struct <structPluginInterface> ( typeSys->allocMan, typeSys, this );
11331151 }
11341152
11351153 DynamicTypeSystem *typeSys;
@@ -1140,7 +1158,7 @@
11401158
11411159 typename staticRegistry::pluginOffset_t offset = 0;
11421160
1143- structPluginInterface *tInterface = eir::static_new_struct <structPluginInterface, allocatorType, exceptMan> ( this, this, typeInfo, sysPtr, construction_params );
1161+ structPluginInterface *tInterface = eir::dyn_new_struct <structPluginInterface, exceptMan> ( this->allocMan, this, this, typeInfo, sysPtr, construction_params );
11441162
11451163 try
11461164 {
@@ -1156,12 +1174,12 @@
11561174
11571175 if ( !staticRegistry::IsOffsetValid( offset ) )
11581176 {
1159- eir::static_del_struct <structPluginInterface, allocatorType> ( this, tInterface );
1177+ eir::dyn_del_struct <structPluginInterface> ( this->allocMan, this, tInterface );
11601178 }
11611179 }
11621180 catch( ... )
11631181 {
1164- eir::static_del_struct <structPluginInterface, allocatorType> ( this, tInterface );
1182+ eir::dyn_del_struct <structPluginInterface> ( this->allocMan, this, tInterface );
11651183
11661184 throw;
11671185 }
@@ -1765,7 +1783,7 @@
17651783
17661784 if ( objMemSize != 0 )
17671785 {
1768- void *allocMem = allocatorType::Allocate( this, objMemSize, objMemAlignment );
1786+ void *allocMem = this->allocMan.Allocate( this, objMemSize, objMemAlignment );
17691787
17701788 if ( allocMem )
17711789 {
@@ -1777,7 +1795,7 @@
17771795 catch( ... )
17781796 {
17791797 // Just to be on the safe side.
1780- allocatorType::Free( this, allocMem );
1798+ this->allocMan.Free( this, allocMem );
17811799
17821800 throw;
17831801 }
@@ -1785,7 +1803,7 @@
17851803 if ( !objOut )
17861804 {
17871805 // Deallocate the memory again, as we seem to have failed.
1788- allocatorType::Free( this, allocMem );
1806+ this->allocMan.Free( this, allocMem );
17891807 }
17901808 }
17911809 }
@@ -1922,7 +1940,7 @@
19221940
19231941 if ( allocMemSize != 0 )
19241942 {
1925- void *allocMem = allocatorType::Allocate( this, allocMemSize, allocMemAlignment );
1943+ void *allocMem = this->allocMan.Allocate( this, allocMemSize, allocMemAlignment );
19261944
19271945 if ( allocMem )
19281946 {
@@ -1933,7 +1951,7 @@
19331951 if ( !objOut )
19341952 {
19351953 // Deallocate the memory again, as we seem to have failed.
1936- allocatorType::Free( this, allocMem );
1954+ this->allocMan.Free( this, allocMem );
19371955 }
19381956 }
19391957 }
@@ -2053,11 +2071,8 @@
20532071 // Reference the type info.
20542072 ReferenceTypeInfo( typeInfo );
20552073
2056- // Get the specialization interface.
2057- typeInterface *tInterface = typeInfo->tInterface;
2058-
20592074 // Get a pointer to GenericRTTI and the object memory.
2060- size_t baseStructAlignment = tInterface->GetTypeAlignment( sysPtr );
2075+ size_t baseStructAlignment = alignof( langType );
20612076
20622077 void *objMem = GetObjectMemoryFromAllocation( allocMem, baseStructAlignment );
20632078
@@ -2097,7 +2112,7 @@
20972112 else
20982113 {
20992114 // We failed, so destruct the class again.
2100- tInterface->Destruct( objMem );
2115+ tmpObj->~langType();
21012116 }
21022117 }
21032118
@@ -2145,7 +2160,7 @@
21452160 size_t objMemAlignment;
21462161 size_t objMemSize = this->_GetTypeStructSizeByRTTI <langType> ( sysPtr, typeInfo, objMemAlignment );
21472162
2148- void *allocMem = allocatorType::Allocate( this, objMemSize, objMemAlignment );
2163+ void *allocMem = this->allocMan.Allocate( this, objMemSize, objMemAlignment );
21492164
21502165 if ( allocMem )
21512166 {
@@ -2157,7 +2172,7 @@
21572172 catch( ... )
21582173 {
21592174 // Just to be on the safe side.
2160- allocatorType::Free( this, allocMem );
2175+ this->allocMan.Free( this, allocMem );
21612176
21622177 throw;
21632178 }
@@ -2165,7 +2180,7 @@
21652180 if ( !objOut )
21662181 {
21672182 // Deallocate the memory again, as we seem to have failed.
2168- allocatorType::Free( this, allocMem );
2183+ this->allocMan.Free( this, allocMem );
21692184 }
21702185 }
21712186 }
@@ -2183,6 +2198,166 @@
21832198 return objOut;
21842199 }
21852200
2201+ // Internalizes a given non-DTS object into this DTS structure so that it is turned into a regular runtime object
2202+ // with attached GenericRTTI struct and plugins. The oldObj object memory has to have been allocated by the
2203+ // same allocator as is assigned to this DTS. Returns nullptr if the internalization process has failed (for example
2204+ // out-of-memory condition when forced to allocate new memory block, plugin construction failing, etc).
2205+ // This method has optimal performance when it is able to reuse the memory pointed at by oldObj, moving around
2206+ // the content in the process. In the worst case a new memory block is allocated which in itself is equal to
2207+ // manually moving oldObj into a DTS runtime object.
2208+ // The size of the object memory pointed at by oldObj has to be exactly sizeof(langType).
2209+ template <typename langType> requires ( eir::nothrow_constructible_from <langType, langType&&> && std::is_nothrow_destructible <langType>::value )
2210+ inline langType* RepurposeByRTTI( systemPointer_t *sysPtr, langType *oldObj )
2211+ {
2212+#ifdef _DEBUG
2213+ rtti_assert( oldObj != nullptr );
2214+#endif //_DEBUG
2215+
2216+ typeInfoBase *typeInfo = this->FindTypeInfoByRTTI <langType> ();
2217+
2218+ if ( typeInfo == nullptr )
2219+ {
2220+ goto failure;
2221+ }
2222+
2223+ {
2224+ size_t langType_sizeof = sizeof(langType);
2225+ size_t langType_alignof = alignof(langType);
2226+
2227+ size_t rtobj_alignof;
2228+ size_t rtobj_sizeof = this->_GetTypeStructSizeByRTTI <langType> ( sysPtr, typeInfo, rtobj_alignof );
2229+
2230+ void *take_mem = nullptr;
2231+
2232+ // We take advantage of the fact that alignments have to be powers-of-two.
2233+ // Check that the memory pointed at by oldObj meets the alignment requirements.
2234+ if ( langType_alignof >= rtobj_alignof )
2235+ {
2236+ // Check that the object memory can be extended to host the new type.
2237+ bool couldBeExtended = false;
2238+
2239+ if constexpr ( eir::ResizeMemoryAllocator <allocatorType> )
2240+ {
2241+ couldBeExtended = this->allocMan.Resize( this, oldObj, rtobj_sizeof );
2242+ }
2243+ else if constexpr ( std::is_trivially_move_assignable <langType>::value &&
2244+ std::is_trivially_move_constructible <langType>::value &&
2245+ eir::ReallocMemoryAllocator <allocatorType> )
2246+ {
2247+ void *realloc_result = this->allocMan.Realloc( this, oldObj, rtobj_sizeof, rtobj_alignof );
2248+
2249+ if ( realloc_result == nullptr )
2250+ {
2251+ goto failure;
2252+ }
2253+
2254+ oldObj = (langType*)realloc_result;
2255+
2256+ couldBeExtended = true;
2257+ }
2258+
2259+ if ( couldBeExtended )
2260+ {
2261+ // Move the language object to the right spot and the construct the meta-information surrounding it.
2262+ take_mem = oldObj;
2263+ }
2264+ }
2265+
2266+ // Go the default route.
2267+ if ( take_mem == nullptr )
2268+ {
2269+ take_mem = this->allocMan.Allocate( this, rtobj_sizeof, rtobj_alignof );
2270+
2271+ if ( take_mem == nullptr )
2272+ {
2273+ goto failure;
2274+ }
2275+ }
2276+
2277+ try
2278+ {
2279+ // Reference the type info.
2280+ ReferenceTypeInfo( typeInfo );
2281+ }
2282+ catch( ... )
2283+ {
2284+ goto failure;
2285+ }
2286+
2287+ // Prevent uninitialized vars after jump.
2288+ {
2289+ // Get a pointer to GenericRTTI and the object memory.
2290+ size_t baseStructAlignment = alignof( langType );
2291+
2292+ void *objMem = GetObjectMemoryFromAllocation( take_mem, baseStructAlignment );
2293+
2294+ GenericRTTI *objTypeMeta = GetTypeStructFromObject( objMem );
2295+
2296+ // Initialize the RTTI struct.
2297+ objTypeMeta->type_meta = typeInfo;
2298+#ifdef _DEBUG
2299+ objTypeMeta->typesys_ptr = this;
2300+#endif //_DEBUG
2301+
2302+ // Initialize the language object.
2303+ langType *tmpObj;
2304+
2305+ // TODO: we could optimize for non-intersection of memory buffers here.
2306+
2307+ if ( take_mem == oldObj )
2308+ {
2309+ langType tmp( std::move( *oldObj ) );
2310+
2311+ oldObj->~langType();
2312+
2313+ tmpObj = new (objMem) langType( std::move( tmp ) );
2314+ }
2315+ else
2316+ {
2317+ // Attempt to construct the language part.
2318+ tmpObj = new (objMem) langType( std::move( *oldObj ) );
2319+
2320+ eir::dyn_del_struct <langType> ( this->allocMan, this, oldObj );
2321+ }
2322+
2323+ langType *objOut = nullptr;
2324+
2325+ if ( tmpObj )
2326+ {
2327+ // Only proceed if we have successfully constructed the object struct.
2328+ // Now construct the plugins.
2329+ bool pluginConstructSuccess = ConstructPlugins( sysPtr, typeInfo, objTypeMeta );
2330+
2331+ if ( pluginConstructSuccess )
2332+ {
2333+ // We are finished! Return the new language object.
2334+ objOut = tmpObj;
2335+ }
2336+ else
2337+ {
2338+ // We failed, so destroy the class again.
2339+ tmpObj->~langType();
2340+ }
2341+ }
2342+
2343+ if ( objOut == nullptr )
2344+ {
2345+ // Since we did not return a proper object, dereference again.
2346+ DereferenceTypeInfo( typeInfo );
2347+
2348+ // Delete the allocated memory.
2349+ this->allocMan.Free( this, take_mem );
2350+ }
2351+
2352+ return objOut;
2353+ }
2354+ }
2355+
2356+ failure:
2357+ eir::dyn_del_struct <langType> ( this->allocMan, this, oldObj );
2358+ return nullptr;
2359+ }
2360+
21862361 // *** RTTI CONSTRUCTION INTERFACE END
21872362
21882363 // THREAD-SAFE, because single atomic operation.
@@ -2421,7 +2596,7 @@
24212596
24222597 void *allocMem = GetAllocationFromTypeStruct( typeStruct, baseStructAlignment );
24232598
2424- allocatorType::Free( this, allocMem );
2599+ this->allocMan.Free( this, allocMem );
24252600 }
24262601
24272602 // Calling this method is only permitted on types that YOU KNOW
@@ -2564,22 +2739,30 @@
25642739
25652740 inline void* Allocate( void *_, size_t memSize, size_t alignment ) noexcept
25662741 {
2567- return allocatorType::Allocate( this->refMem, memSize, alignment );
2742+ DynamicTypeSystem *refMem = this->refMem;
2743+
2744+ return refMem->allocMan.Allocate( refMem, memSize, alignment );
25682745 }
25692746
25702747 inline bool Resize( void *_, void *memPtr, size_t reqSize ) noexcept requires( eir::ResizeMemoryAllocator <allocatorType> )
25712748 {
2572- return allocatorType::Resize( this->refMem, memPtr, reqSize );
2749+ DynamicTypeSystem *refMem = this->refMem;
2750+
2751+ return refMem->allocMan.Resize( refMem, memPtr, reqSize );
25732752 }
25742753
25752754 inline void* Realloc( void *_, void *memPtr, size_t reqSize, size_t reqAlignment ) noexcept requires( eir::ReallocMemoryAllocator <allocatorType> )
25762755 {
2577- return allocatorType::Realloc( this->refMem, memPtr, reqSize, reqAlignment );
2756+ DynamicTypeSystem *refMem = this->refMem;
2757+
2758+ return refMem->allocMan.Realloc( refMem, memPtr, reqSize, reqAlignment );
25782759 }
25792760
25802761 inline void Free( void *_, void *memPtr ) noexcept
25812762 {
2582- allocatorType::Free( this->refMem, memPtr );
2763+ DynamicTypeSystem *refMem = this->refMem;
2764+
2765+ refMem->allocMan.Free( refMem, memPtr );
25832766 }
25842767
25852768 DynamicTypeSystem *refMem;
@@ -2752,6 +2935,6 @@
27522935 };
27532936
27542937 // Redirect from structRegistry to typeInfoBase.
2755-IMPL_HEAP_REDIR_DIRECTRPTR_ALLOC_TEMPLATEBASE( DynamicTypeSystem, DTS_TEMPLARGS_NODEF, DTS_TEMPLUSE, structRegRedirAlloc, typeInfoBase, structRegistry, typeSys, allocatorType );
2938+IMPL_HEAP_REDIR_DYNRPTR_ALLOC_TEMPLATEBASE( DynamicTypeSystem, DTS_TEMPLARGS_NODEF, DTS_TEMPLUSE, structRegRedirAlloc, typeInfoBase, structRegistry, typeSys, allocMan, allocatorType );
27562939
27572940 #endif //_DYN_TYPE_ABSTRACTION_SYSTEM_
--- unittests/src/dynamictypesystem.cpp (revision 447)
+++ unittests/src/dynamictypesystem.cpp (revision 448)
@@ -7,6 +7,8 @@
77 #include <sdk/OSUtils.memheap.h>
88 #include <sdk/eirutils.h>
99
10+#include "alloc_helper.hxx"
11+
1012 DEFINE_HEAP_REDIR_ALLOC_IMPL( dtsHeapAllocator );
1113
1214 typedef DynamicTypeSystem <dtsHeapAllocator, void, dtsDefaultLockProvider> testTypeSystem_t;
@@ -648,6 +650,33 @@
648650 }
649651 printf( "ok.\n" );
650652
653+ printf( "testing DTS with object allocator..." );
654+ {
655+ DynamicTypeSystem <EirHeapLinkAllocator, void> dts( eir::constr_with_alloc::DEFAULT, &globalHeapAlloc );
656+
657+ decltype(dts)::typeInfoBase *typeInfo = dts.RegisterStructType <int> ( "int" );
658+
659+ assert( typeInfo != nullptr );
660+
661+ GenericRTTI *rtobj = dts.Construct( nullptr, typeInfo, nullptr );
662+
663+ assert( rtobj != nullptr );
664+
665+ dts.Destroy( nullptr, rtobj );
666+ }
667+ printf( "ok.\n" );
668+
669+ printf( "testing DTS FindTypeInfoByRTTI..." );
670+ {
671+ DynamicTypeSystem <CRTHeapAllocator, void> dts;
672+
673+ decltype(dts)::typeInfoBase *typeInfo = dts.RegisterStructType <testObject> ( "testObject" );
674+
675+ assert( typeInfo != nullptr );
676+ assert( dts.FindTypeInfoByRTTI <testObject> () != nullptr );
677+ }
678+ printf( "ok.\n" );
679+
651680 printf( "testing DTS ConstructByRTTI (simple construction)..." );
652681 {
653682 DynamicTypeSystem <CRTHeapAllocator, void> dts;
@@ -745,4 +774,101 @@
745774 dts.Destroy( nullptr, rtobj );
746775 }
747776 printf( "ok.\n" );
777+
778+ printf( "testing DTS RepurposeByRTTI (with CRT Heap)..." );
779+ {
780+ // TRIVIALLY MOVEABLE.
781+ {
782+ struct alignas(32) obj
783+ {
784+ int value = 99;
785+ };
786+
787+ obj *myobj = eir::static_new_struct <obj, CRTHeapAllocator> ( nullptr );
788+
789+ myobj->value = 34;
790+
791+ DynamicTypeSystem <CRTHeapAllocator, void> dts;
792+
793+ decltype(dts)::typeInfoBase *typeInfo = dts.RegisterStructType <obj> ( "obj" );
794+
795+ assert( typeInfo != nullptr );
796+
797+ obj *intern = dts.RepurposeByRTTI <obj> ( nullptr, myobj );
798+
799+ assert( intern != nullptr );
800+ assert( intern->value == 34 );
801+
802+ GenericRTTI *rtintern = decltype(dts)::GetTypeStructFromObject( intern );
803+
804+ dts.Destroy( nullptr, rtintern );
805+ }
806+
807+ // NOT TRIVIALLY MOVEABLE.
808+ {
809+ struct alignas(32) obj
810+ {
811+ obj( void ) = default;
812+ obj( const obj& ) = delete;
813+ obj( obj&& right ) noexcept
814+ {
815+ value = right.value;
816+
817+ right.value = 99;
818+ }
819+
820+ int value = 99;
821+ };
822+
823+ obj *myobj = eir::static_new_struct <obj, CRTHeapAllocator> ( nullptr );
824+
825+ myobj->value = 51;
826+
827+ DynamicTypeSystem <CRTHeapAllocator, void> dts;
828+
829+ decltype(dts)::typeInfoBase *typeInfo = dts.RegisterStructType <obj> ( "obj" );
830+
831+ assert( typeInfo != nullptr );
832+
833+ obj *intern = dts.RepurposeByRTTI <obj> ( nullptr, myobj );
834+
835+ assert( intern != nullptr );
836+ assert( intern->value == 51 );
837+
838+ GenericRTTI *rtintern = decltype(dts)::GetTypeStructFromObject( intern );
839+
840+ dts.Destroy( nullptr, rtintern );
841+ }
842+ }
843+ printf( "ok.\n" );
844+
845+ printf( "testing DTS RepurposeByRTTI (with Eir Heap)..." );
846+ {
847+ struct alignas(32) obj
848+ {
849+ int value = 99;
850+ };
851+
852+ EirHeapLinkAllocator alloc( &globalHeapAlloc );
853+
854+ DynamicTypeSystem <EirHeapLinkAllocator, void> dts( eir::constr_with_alloc::DEFAULT, alloc );
855+
856+ decltype(dts)::typeInfoBase *typeInfo = dts.RegisterStructType <obj> ( "obj" );
857+
858+ assert( typeInfo != nullptr );
859+
860+ obj *myobj = eir::dyn_new_struct <obj> ( alloc, nullptr );
861+
862+ myobj->value = 34;
863+
864+ obj *intern = dts.RepurposeByRTTI <obj> ( nullptr, myobj );
865+
866+ assert( intern != nullptr );
867+ assert( intern->value == 34 );
868+
869+ GenericRTTI *rtintern = decltype(dts)::GetTypeStructFromObject( intern );
870+
871+ dts.Destroy( nullptr, rtintern );
872+ }
873+ printf( "ok.\n" );
748874 }
Show on old repository browser