• R/O
  • SSH
  • HTTPS

eirrepo: Commit


Commit MetaInfo

Revision445 (tree)
Time2022-02-17 03:53:40
Authorquiret

Log Message

- added a DTS unit-test about extending the type plugin system with a new interface that can be used for calculating on plugin memory

Change Summary

Incremental Difference

--- common/sdk/DynamicTypeSystem.h (revision 444)
+++ common/sdk/DynamicTypeSystem.h (revision 445)
@@ -412,6 +412,13 @@
412412 return this->name;
413413 }
414414
415+ // Returns the plugin struct registry of this type. Plugin information can
416+ // be used to perform additional tasks as described by the plugin interfaces.
417+ inline const structRegistry_t& GetPluginRegistry( void ) const noexcept
418+ {
419+ return this->structRegistry;
420+ }
421+
415422 protected:
416423 // Helper for the Cleanup method.
417424 typedef allocatorType typeInfoAllocatorType;
--- common/sdk/MemoryUtils.h (revision 444)
+++ common/sdk/MemoryUtils.h (revision 445)
@@ -19,6 +19,9 @@
1919 #include <atomic>
2020 #include <type_traits>
2121
22+// TODO: the classes in this header need proper unit-tests; we need to even still finish some of them;
23+// also we should add C++20 concepts where they are long due.
24+
2225 template <typename numberType, typename managerType>
2326 struct FirstPassAllocationSemantics
2427 {
@@ -72,9 +75,6 @@
7275
7376 blockIter_t appendNode = manager.GetRootNode();
7477
75- // Make sure we align to the system integer (by default).
76- // todo: maybe this is not correct all the time?
77-
7878 for ( blockIter_t iter( manager.GetFirstMemoryBlock() ); manager.IsEndMemoryBlock( iter ) == false; iter.Increment() )
7979 {
8080 // Intersect the current memory slice with the ones on our list.
--- common/sdk/PluginFactory.h (revision 444)
+++ common/sdk/PluginFactory.h (revision 445)
@@ -46,7 +46,6 @@
4646 // The structure of this memory heap is then applied onto the underlying type.
4747 typedef InfiniteCollisionlessBlockAllocator <size_t> blockAlloc_t;
4848
49- // TODO: actually make our own allocation semantics manager so we get rid of blockAlloc_t
5049 typedef blockAlloc_t::allocSemanticsManager allocSemanticsManager;
5150
5251 blockAlloc_t pluginRegions;
@@ -53,39 +52,13 @@
5352
5453 typedef typename pluginDescriptorType::pluginOffset_t pluginOffset_t;
5554
55+private:
5656 size_t requiredMemoryAlignment;
5757
58- inline AnonymousPluginStructRegistry( void ) noexcept
59- {
60- this->requiredMemoryAlignment = 1; // by default we do not need any special alignment.
61- }
62- inline AnonymousPluginStructRegistry( AnonymousPluginStructRegistry&& ) noexcept = default;
63- inline AnonymousPluginStructRegistry( const AnonymousPluginStructRegistry& ) = delete;
64-
65- inline ~AnonymousPluginStructRegistry( void )
66- {
67- // TODO: allow custom memory allocators.
68-
69- // The runtime is allowed to destroy with plugins still attached, so clean up.
70- while ( this->regPlugins.GetCount() != 0 )
71- {
72- registered_plugin& thePlugin = this->regPlugins[ 0 ];
73-
74- thePlugin.descriptor->DeleteOnUnregister();
75-
76- this->regPlugins.RemoveByIndex( 0 );
77- }
78- }
79-
80- inline AnonymousPluginStructRegistry& operator = ( AnonymousPluginStructRegistry&& ) noexcept = default;
81- inline AnonymousPluginStructRegistry& operator = ( const AnonymousPluginStructRegistry& ) = delete;
82-
83- // Oh my fucking god. "template" can be used other than declaring a templated type?
84- // Why does C++ not make it a job for the compiler to determine things... I mean it would be possible!
85- // You cannot know what a pain in the head it is to find the solution to add the "template" keyword.
86- // Bjarne, seriously.
58+ // The "template" keyword makes sense because the specifier "pluginInterfaceBase" cannot be deduced from the global program graph.
8759 typedef typename pluginAvailabilityDispatchType::template pluginInterfaceBase <AnonymousPluginStructRegistry> pluginInterfaceBase;
8860
61+public:
8962 // Virtual interface used to describe plugin classes.
9063 // The construction process must be immutable across the runtime.
9164 struct pluginInterface : public pluginInterfaceBase
@@ -92,6 +65,7 @@
9265 {
9366 virtual ~pluginInterface( void ) {}
9467
68+ // Overwrite this method to construct the plugin memory.
9569 virtual bool OnPluginConstruct( abstractionType *object, pluginOffset_t pluginOffset, pluginDescriptorType pluginId, AdditionalArgs... )
9670 {
9771 // By default, construction of plugins should succeed.
@@ -98,11 +72,13 @@
9872 return true;
9973 }
10074
75+ // Overwrite this method to destroy the plugin memory.
10176 virtual void OnPluginDestruct( abstractionType *object, pluginOffset_t pluginOffset, pluginDescriptorType pluginId, AdditionalArgs... ) noexcept
10277 {
10378 return;
10479 }
10580
81+ // Overwrite this method to copy-assign the plugin memory.
10682 virtual bool OnPluginCopyAssign( abstractionType *dstObject, const abstractionType *srcObject, pluginOffset_t pluginOffset, pluginDescriptorType pluginId, AdditionalArgs... )
10783 {
10884 // Copy-assignment of data to another plugin struct is optional.
@@ -109,6 +85,7 @@
10985 return false;
11086 }
11187
88+ // Overwrite this method to move-assign the plugin memory.
11289 virtual bool OnPluginMoveAssign( abstractionType *dstObject, abstractionType *srcObject, pluginOffset_t pluginOffset, pluginDescriptorType pluginId, AdditionalArgs... )
11390 {
11491 // Mpve-assignment of data to another plugin struct is optional.
@@ -115,9 +92,10 @@
11592 return false;
11693 }
11794
95+ // Overwrite this method if unregistering should delete this class or other cleanup has to be performed.
96+ // This allows cleanup using custom allocators whose pointer-to is stored inside this interface itself.
11897 virtual void DeleteOnUnregister( void ) noexcept
11998 {
120- // Overwrite this method if unregistering should delete this class.
12199 return;
122100 }
123101 };
@@ -125,6 +103,8 @@
125103 // Struct that holds information about registered plugins.
126104 struct registered_plugin : public blockAlloc_t::block_t
127105 {
106+ friend struct AnonymousPluginStructRegistry;
107+
128108 inline registered_plugin( void ) noexcept
129109 {
130110 this->pluginSize = 0;
@@ -165,6 +145,32 @@
165145 }
166146 inline registered_plugin& operator = ( const registered_plugin& right ) = delete;
167147
148+ inline size_t GetPluginSize( void ) const noexcept
149+ {
150+ return this->pluginSize;
151+ }
152+
153+ inline size_t GetPluginAlignment( void ) const noexcept
154+ {
155+ return this->pluginAlignment;
156+ }
157+
158+ inline const pluginDescriptorType& GetDescriptor( void ) const noexcept
159+ {
160+ return this->pluginId;
161+ }
162+
163+ inline pluginOffset_t GetPluginOffset( void ) const noexcept
164+ {
165+ return this->pluginOffset;
166+ }
167+
168+ inline pluginInterface* GetInterface( void ) const noexcept
169+ {
170+ return this->descriptor;
171+ }
172+
173+ private:
168174 size_t pluginSize;
169175 size_t pluginAlignment;
170176 pluginDescriptorType pluginId;
@@ -172,6 +178,7 @@
172178 pluginInterface *descriptor;
173179 };
174180
181+private:
175182 DEFINE_HEAP_REDIR_ALLOC_BYSTRUCT( regPluginsRedirAlloc, allocatorType );
176183
177184 // Container that holds plugin information.
@@ -180,8 +187,44 @@
180187 registeredPlugins_t regPlugins;
181188
182189 // Holds things like the way to determine the size of all plugins.
183- pluginAvailabilityDispatchType regBoundFlavor;
190+ [[no_unique_address]] pluginAvailabilityDispatchType regBoundFlavor;
191+
192+public:
193+ inline AnonymousPluginStructRegistry( void ) noexcept
194+ {
195+ this->requiredMemoryAlignment = 1; // by default we do not need any special alignment.
196+ }
197+ inline AnonymousPluginStructRegistry( AnonymousPluginStructRegistry&& right ) noexcept
198+ : pluginRegions( std::move( right.pluginRegions ) ), requiredMemoryAlignment( std::move( right.requiredMemoryAlignment ) ),
199+ regPlugins( std::move( right.regPlugins ) ), regBoundFlavor( std::move( right.regBoundFlavor ) )
200+ {
201+ right.requiredMemoryAlignment = 1;
202+ }
203+ inline AnonymousPluginStructRegistry( const AnonymousPluginStructRegistry& ) = delete;
184204
205+ inline ~AnonymousPluginStructRegistry( void )
206+ {
207+ // TODO: allow custom memory allocators.
208+
209+ // The runtime is allowed to destroy with plugins still attached, so clean up.
210+ while ( this->regPlugins.GetCount() != 0 )
211+ {
212+ registered_plugin& thePlugin = this->regPlugins[ 0 ];
213+
214+ thePlugin.descriptor->DeleteOnUnregister();
215+
216+ this->regPlugins.RemoveByIndex( 0 );
217+ }
218+ }
219+
220+ inline AnonymousPluginStructRegistry& operator = ( AnonymousPluginStructRegistry&& right ) noexcept
221+ {
222+ this->~AnonymousPluginStructRegistry();
223+
224+ return *new (this) AnonymousPluginStructRegistry( std::move( right ) );
225+ }
226+ inline AnonymousPluginStructRegistry& operator = ( const AnonymousPluginStructRegistry& ) = delete;
227+
185228 inline size_t GetPluginSizeByRuntime( void ) const
186229 {
187230 return this->regBoundFlavor.GetPluginAllocSize( this );
@@ -197,6 +240,24 @@
197240 return this->requiredMemoryAlignment;
198241 }
199242
243+ inline const registeredPlugins_t& GetRegisteredPlugins( void ) const noexcept
244+ {
245+ return this->regPlugins;
246+ }
247+
248+ inline pluginInterface* GetPluginInterfaceByPluginOffset( pluginOffset_t off ) const noexcept
249+ {
250+ for ( const registered_plugin& plg : this->regPlugins )
251+ {
252+ if ( plg.pluginOffset == off )
253+ {
254+ return plg.descriptor;
255+ }
256+ }
257+
258+ return nullptr;
259+ }
260+
200261 // Function used to register a new plugin struct into the class.
201262 inline pluginOffset_t RegisterPlugin( size_t pluginSize, size_t pluginAlignment, const pluginDescriptorType& pluginId, pluginInterface *plugInterface, size_t allocStart = 0 )
202263 {
@@ -490,7 +551,7 @@
490551
491552 // Use this function whenever you receive a handle offset to a plugin struct.
492553 // It is optimized so that you cannot go wrong.
493- inline pluginOffset_t ResolvePluginStructOffsetByRuntime( pluginOffset_t handleOffset )
554+ inline pluginOffset_t ResolvePluginStructOffsetByRuntime( pluginOffset_t handleOffset ) const
494555 {
495556 size_t theActualOffset;
496557
@@ -499,7 +560,7 @@
499560 return ( gotOffset ? theActualOffset : 0 );
500561 }
501562
502- inline pluginOffset_t ResolvePluginStructOffsetByObject( const abstractionType *obj, pluginOffset_t handleOffset )
563+ inline pluginOffset_t ResolvePluginStructOffsetByObject( const abstractionType *obj, pluginOffset_t handleOffset ) const
503564 {
504565 size_t theActualOffset;
505566
--- common/sdk/PluginFlavors.h (revision 444)
+++ common/sdk/PluginFlavors.h (revision 445)
@@ -20,6 +20,8 @@
2020 template <typename flavorType, typename abstractionType>
2121 concept PluginStructRegistryFlavor =
2222 eir::constructible_from <flavorType> &&
23+ eir::nothrow_constructible_from <flavorType, flavorType&&> &&
24+ std::is_nothrow_assignable <flavorType&, flavorType&&>::value &&
2325 requires ( flavorType FT, size_t& S_OUT, const abstractionType *ATPTR, const void *MNGPTR ) {
2426 { FT.GetPluginStructOffset( MNGPTR, size_t(), S_OUT ) } -> std::same_as <bool>;
2527 { FT.GetPluginStructOffsetByObject( MNGPTR, ATPTR, size_t(), S_OUT ) } -> std::same_as <bool>;
@@ -33,7 +35,7 @@
3335
3436 // Struct registry flavor is used to fine-tune the performance of said registry by extending it with features.
3537 // The idea is that we maximize performance by only giving it the features you really want it to have.
36-template <typename abstractionType, typename... pluginInterfaceBases> requires ( std::is_fundamental <pluginInterfaceBases>::value && ... )
38+template <typename abstractionType, typename... pluginInterfaceBases> requires ( ( std::is_fundamental <pluginInterfaceBases>::value == false ) && ... )
3739 struct cachedMinimalStructRegistryFlavor
3840 {
3941 size_t pluginAllocSize;
@@ -194,10 +196,10 @@
194196 // The given block is always a plugin registration, so cast it appropriately.
195197 const typename managerType::registered_plugin *pluginDesc = (const typename managerType::registered_plugin*)theBlock;
196198
197- pluginInterfaceBase <managerType> *pluginInterface = (pluginInterfaceBase <managerType>*)pluginDesc->descriptor;
199+ pluginInterfaceBase <managerType> *pluginInterface = (pluginInterfaceBase <managerType>*)pluginDesc->GetInterface();
198200
199201 // Lets just ask the vendor, whether he wants the block.
200- bool isAvailable = pluginInterface->IsPluginAvailableDuringRuntime( pluginDesc->pluginId );
202+ bool isAvailable = pluginInterface->IsPluginAvailableDuringRuntime( pluginDesc->GetDescriptor() );
201203
202204 // We ignore a block registration if it is not available.
203205 return ( isAvailable == false );
@@ -308,10 +310,10 @@
308310 // The given block is always a plugin registration, so cast it appropriately.
309311 const typename managerType::registered_plugin *pluginDesc = (const typename managerType::registered_plugin*)theBlock;
310312
311- pluginInterfaceBase <managerType> *pluginInterface = (pluginInterfaceBase <managerType>*)pluginDesc->descriptor;
313+ pluginInterfaceBase <managerType> *pluginInterface = (pluginInterfaceBase <managerType>*)pluginDesc->GetInterface();
312314
313315 // Lets just ask the vendor, whether he wants the block.
314- bool isAvailable = pluginInterface->IsPluginAvailableAtObject( this->aliveObject, pluginDesc->pluginId );
316+ bool isAvailable = pluginInterface->IsPluginAvailableAtObject( this->aliveObject, pluginDesc->GetDescriptor() );
315317
316318 // We ignore a block registration if it is not available.
317319 return ( isAvailable == false );
--- unittests/src/dynamictypesystem.cpp (revision 444)
+++ unittests/src/dynamictypesystem.cpp (revision 445)
@@ -687,7 +687,62 @@
687687
688688 printf( "testing DTS custom calculation method plugin..." );
689689 {
690- // TODO.
690+ struct calculationPluginInterface
691+ {
692+ virtual void OnPluginCalculate( GenericRTTI *obj, void *plgmem ) const
693+ {
694+ return;
695+ }
696+ };
697+
698+ DynamicTypeSystem <CRTHeapAllocator, void, dtsDefaultLockProvider, cachedMinimalStructRegistryFlavor <GenericRTTI, calculationPluginInterface>> dts;
699+
700+ struct simple
701+ {
702+ int value = 33;
703+ };
704+
705+ decltype(dts)::typeInfoBase *type = dts.RegisterStructType <simple> ( "simple" );
706+
707+ assert( type != nullptr );
708+
709+ struct simple_plg
710+ {
711+ float etc = 1.4f;
712+ };
713+
714+ struct simple_plg_intf : public decltype(dts)::functoidHelper_t::dependantStructPluginInterface <simple_plg>
715+ {
716+ void OnPluginCalculate( GenericRTTI *obj, void *plgmem ) const override
717+ {
718+ simple_plg *plg = (simple_plg*)plgmem;
719+
720+ plg->etc += 1.0f;
721+ }
722+ };
723+
724+ decltype(dts)::pluginOffset_t plgoff = dts.RegisterCustomPlugin <simple_plg_intf> ( sizeof(simple_plg), alignof(simple_plg), type );
725+
726+ assert( decltype(dts)::IsOffsetValid( plgoff ) == true );
727+
728+ GenericRTTI *rtobj = dts.Construct( nullptr, type, nullptr );
729+
730+ assert( rtobj != nullptr );
731+
732+ simple_plg *plg = decltype(dts)::RESOLVE_STRUCT <simple_plg> ( nullptr, rtobj, type, plgoff );
733+
734+ assert( plg != nullptr );
735+ assert( plg->etc == 1.4f );
736+
737+ decltype(dts)::pluginInterface *intf = type->GetPluginRegistry().GetPluginInterfaceByPluginOffset( plgoff );
738+
739+ assert( intf != nullptr );
740+
741+ intf->OnPluginCalculate( rtobj, plg );
742+
743+ assert( plg->etc > 1.4f );
744+
745+ dts.Destroy( nullptr, rtobj );
691746 }
692747 printf( "ok.\n" );
693748 }
Show on old repository browser