From 209765def5ae4276b67d84d9db6f358c787ded0f Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 30 Aug 2009 14:11:14 +0200 Subject: [PATCH] WIP: correct indentation, add some comments... --- src/lib/meta/configflags.hpp | 298 ++++++++-------- src/proc/engine/nodeoperation.hpp | 488 +++++++++++++------------- src/proc/engine/nodewiring-config.hpp | 7 +- src/proc/engine/nodewiring.cpp | 5 + tests/lib/meta/config-flags-test.cpp | 5 +- 5 files changed, 405 insertions(+), 398 deletions(-) diff --git a/src/lib/meta/configflags.hpp b/src/lib/meta/configflags.hpp index f0f27012c..82d49bfc5 100644 --- a/src/lib/meta/configflags.hpp +++ b/src/lib/meta/configflags.hpp @@ -31,12 +31,12 @@ ** to generate, filter and process those configurations. The final goal is to ** automatically generate a factory which is able to deliver objects ** configured according to the situation encoded in the flags. - ** + ** ** @note currently there is an inherent limitation to configurations defined by ** a maximum of 5 independent flags. While it is easy to increase this limit, ** you should consider that the final goal is to generate template instantiations, ** which would lead to more and more code bloat with growing number of possible - ** combination. + ** combinations. ** ** @see proc::engine::config::Strategy usage example ** @see proc::engine::config::ConfigSelector @@ -53,153 +53,151 @@ namespace lumiera { - namespace typelist { - - const size_t CONFIG_FLAGS_MAX = 5; - - - template struct Flag { typedef Flag ID; }; - template<> struct Flag<0> { typedef NullType ID; }; - - - template< char f1=0 - , char f2=0 - , char f3=0 - , char f4=0 - , char f5=0 - > - struct Flags - { - typedef typename Types< typename Flag::ID - , typename Flag::ID - , typename Flag::ID - , typename Flag::ID - , typename Flag::ID - >::List - Tuple; - typedef Tuple List; - }; - - - template< char f1=0 - , char f2=0 - , char f3=0 - , char f4=0 - , char f5=0 - > - struct Config ///< distinct type representing a configuration - { - typedef typename Flags::Tuple Flags; - typedef Flags List; - }; - - - - template - struct ConfigSetFlag; ///< set (prepend) the Flag to the given config - - template< char Fl - , char f1 - , char f2 - , char f3 - , char f4 - , char IGN - > - struct ConfigSetFlag > - { - typedef typelist::Config Config; - }; - - - - /** build a configuration type from a list-of-flags */ - template > - struct BuildConfigFromFlags - { - typedef CONF Config; - typedef Config Type; - }; - template - struct BuildConfigFromFlags< Node,FLAGS>, CONF> - { - typedef typename ConfigSetFlag< Fl - , typename BuildConfigFromFlags::Config - >::Config Config; - typedef Config Type; - }; - - /** create a configuration type for the given list-of-flags */ - template - struct DefineConfigByFlags : BuildConfigFromFlags { }; - - - namespace { - /** helper comparing enum values and chars (flags) */ - template - struct maxC - { - enum{ VAL = ii < jj? jj : ii }; - }; - } - - - /** - * Helper for calculating values and for - * invoking runtime code based on a given FlagTuple. - * Can also be used on a Typelist of several Configs. - * The latter case is typically used to invoke an operation - * while enumerating all Flag-Configurations defined in Code. - * An example would be to build (at runtime) an dispatcher table. - * Explanation: For the Case covering a List of Configs, we provide - * a templated visitation function, which can accept a functor object - * to be invoked on each Configuration. - */ - template - struct FlagInfo; - - template - struct FlagInfo, FLAGS> > - { - enum{ BITS = maxC< ff, FlagInfo::BITS> ::VAL - , CODE = (1<::CODE - }; - }; - - template<> - struct FlagInfo - { - enum{ BITS = 0 - , CODE = 0 - }; - - template - static typename FUNC::Ret - accept (FUNC& functor) - { - return functor.done(); - } - }; - - template - struct FlagInfo > - { - typedef typename CONF::Flags ThisFlags; - enum{ - BITS = maxC< FlagInfo::BITS, FlagInfo::BITS > ::VAL - }; - - template - static typename FUNC::Ret - accept (FUNC& functor) - { - functor.template visit(FlagInfo::CODE); - return FlagInfo::accept (functor); - } - }; - - - - } // namespace typelist +namespace typelist{ -} // namespace lumiera + const size_t CONFIG_FLAGS_MAX = 5; + + + template struct Flag { typedef Flag ID; }; + template<> struct Flag<0> { typedef NullType ID; }; + + + template< char f1=0 + , char f2=0 + , char f3=0 + , char f4=0 + , char f5=0 + > + struct Flags + { + typedef typename Types< typename Flag::ID + , typename Flag::ID + , typename Flag::ID + , typename Flag::ID + , typename Flag::ID + >::List + Tuple; + typedef Tuple List; + }; + + + template< char f1=0 + , char f2=0 + , char f3=0 + , char f4=0 + , char f5=0 + > + struct Config ///< distinct type representing a configuration + { + typedef typename Flags::Tuple Flags; + typedef Flags List; + }; + + + + template + struct ConfigSetFlag; ///< set (prepend) the Flag to the given config + + template< char Fl + , char f1 + , char f2 + , char f3 + , char f4 + , char IGN + > + struct ConfigSetFlag > + { + typedef typelist::Config Config; + }; + + + + /** build a configuration type from a list-of-flags */ + template > + struct BuildConfigFromFlags + { + typedef CONF Config; + typedef Config Type; + }; + template + struct BuildConfigFromFlags< Node,FLAGS>, CONF> + { + typedef typename ConfigSetFlag< Fl + , typename BuildConfigFromFlags::Config + >::Config Config; + typedef Config Type; + }; + + /** create a configuration type for the given list-of-flags */ + template + struct DefineConfigByFlags : BuildConfigFromFlags { }; + + + namespace { + /** helper comparing enum values and chars (flags) */ + template + struct maxC + { + enum{ VAL = ii < jj? jj : ii }; + }; + } + + + /** + * Helper for calculating values and for + * invoking runtime code based on a given FlagTuple. + * Can also be used on a Typelist of several Configs. + * The latter case is typically used to invoke an operation + * while enumerating all Flag-Configurations defined in Code. + * An example would be to build (at runtime) an dispatcher table. + * Explanation: For the Case covering a List of Configs, we provide + * a templated visitation function, which can accept a functor object + * to be invoked on each Configuration. + */ + template + struct FlagInfo; + + template + struct FlagInfo, FLAGS> > + { + enum{ BITS = maxC< ff, FlagInfo::BITS> ::VAL + , CODE = (1<::CODE + }; + }; + + template<> + struct FlagInfo + { + enum{ BITS = 0 + , CODE = 0 + }; + + template + static typename FUNC::Ret + accept (FUNC& functor) + { + return functor.done(); + } + }; + + template + struct FlagInfo > + { + typedef typename CONF::Flags ThisFlags; + enum{ + BITS = maxC< FlagInfo::BITS, FlagInfo::BITS > ::VAL + }; + + template + static typename FUNC::Ret + accept (FUNC& functor) + { + functor.template visit(FlagInfo::CODE); + return FlagInfo::accept (functor); + } + }; + + + +}} // namespace lumiera::typelist #endif diff --git a/src/proc/engine/nodeoperation.hpp b/src/proc/engine/nodeoperation.hpp index 9ab36e93c..d3a36067d 100644 --- a/src/proc/engine/nodeoperation.hpp +++ b/src/proc/engine/nodeoperation.hpp @@ -26,7 +26,7 @@ ** and enables to pull a result frames from the nodes. Especially, the aspect of ** buffer management and cache query is covered here. Each node has been preconfigured by ** the builder with a WiringDescriptor and a concrete type of a StateAdapter, including - ** a specific Configuration, because the node can be built to + ** a specific Configuration, because the node can be built to ** - participate in the Caching or ignore the cache ** - actually process a result or just pull frames from a source ** - employ in-Place calculations or use separate in/out buffers @@ -42,15 +42,15 @@ ** configurations are pre-built while compiling (it's a small number below 32 configuration instance). ** To be able to select the Strategy for each configuration, we need a Factory (ConfigSelector defined in ** nodewiring-config.hpp). which is actually instantiated and used in nodewiring.cpp, which is the object - ** file holding all those instantiations. - ** + ** file holding all those instantiations. + ** ** @see engine::ProcNode ** @see engine::Invocation ** @see engine::State ** @see engine::NodeFactory ** @see nodewiring-config.hpp ** @see nodewiring.hpp interface for building/wiring the nodes - ** + ** */ #ifndef ENGINE_NODEOPERATION_H @@ -71,249 +71,249 @@ namespace engine { - namespace config { - - - /** - * Base class of all concrete invocation sequences. - * Could contain a collection of functions used to build up the invocation sequence. - * Currently contains just a marker used to detect the existence of an concrete - * definition/specialisation for a given specific configuration. - */ - class OperationBase - { - typedef lumiera::Yes_t is_defined; - - - }; - - - template - struct QueryCache : NEXT - { - BuffHandle - step (Invocation& ivo) - { - BuffHandle fetched = ivo.fetch (ivo.genFrameID()); - if (fetched) - return fetched; - else - return NEXT::step (ivo); - } - }; - - - template - struct AllocBufferTable : NEXT - { - BuffHandle - step (Invocation& ivo) - { - BuffTableChunk buffTab (ivo.wiring, ivo.getBuffTableStorage()); - ivo.setBuffTab(&buffTab); - ASSERT (ivo.buffTab); - ASSERT (ivo.buffTab_isConsistent()); - - return NEXT::step (ivo); - } - }; - - - template - struct PullInput : NEXT - { - BuffHandle - step (Invocation& ivo) - { - BuffHandle * inH = ivo.buffTab->inHandle; - BuffHandle::PBuff *inBuff = ivo.buffTab->inBuff; - - for (uint i = 0; i < ivo.nrI(); ++i ) - { - inBuff[i] = - *(inH[i] = this->pullPredecessor(ivo,i)); // invoke predecessor - // now Input #i is ready... - } - return NEXT::step (ivo); - } - }; - - - template - struct ReadSource : NEXT - { - BuffHandle - step (Invocation& ivo) - { - BuffHandle *inH = ivo.buffTab->inHandle; - BuffHandle *outH = ivo.buffTab->outHandle; - BuffHandle::PBuff *inBuff = ivo.buffTab->inBuff; - BuffHandle::PBuff *outBuff = ivo.buffTab->outBuff; - - ASSERT (ivo.nrO() == ivo.nrI() ); - - for (uint i = 0; i < ivo.nrI(); ++i ) - { - inBuff[i] = outBuff[i] = - *(inH[i] = outH[i] = this->getSource(ivo,i)); - // now Input #i is ready... - } - return NEXT::step (ivo); - } - }; - - - template - struct AllocOutput : NEXT - { - BuffHandle - step (Invocation& ivo) - { - ASSERT (ivo.buffTab); - ASSERT (ivo.nrO() < ivo.buffTabSize()); - BuffHandle *outH = ivo.buffTab->outHandle; - BuffHandle::PBuff *outBuff = ivo.buffTab->outBuff; - - for (uint i = 0; i < ivo.nrO(); ++i ) - { - outBuff[i] = - *(outH[i] = ivo.allocateBuffer (ivo.wiring.out[i].bufferType)); - // now Output buffer for channel #i is available... - } - return NEXT::step (ivo); - } - }; - - - template - struct ProcessData : NEXT - { - BuffHandle - step (Invocation& ivo) - { - ASSERT (ivo.buffTab); - ASSERT (ivo.buffTab_isConsistent()); - ASSERT (this->validateBuffers(ivo)); - - // Invoke our own process() function, - // providing the array of outBuffer+inBuffer ptrs - ivo.wiring.procFunction (ivo.buffTab->outBuff); - - return NEXT::step (ivo); - } - }; - - template - struct FeedCache : NEXT - { - BuffHandle - step (Invocation& ivo) - { - for (uint i = 0; i < ivo.nrO(); ++i ) - { - // declare all Outputs as finished - ivo.is_calculated(ivo.buffTab->outHandle[i]); - } - - return NEXT::step (ivo); - } - }; - - template - struct ReleaseBuffers : NEXT /////////////////TODO: couldn't this be done automatically by BuffTab's dtor?? - { ///////////////// this would require BuffHandle to be a smart ref.... - BuffHandle - step (Invocation& ivo) - { - // all buffers besides the required Output no longer needed - this->releaseBuffers(ivo.buffTab->outHandle, - ivo.buffTabSize(), - ivo.outNr); - - return ivo.buffTab->outHandle[ivo.outNr]; - } - }; - - - - - - /* =============================================================== */ - /* === declare the possible Assembly of these elementary steps === */ - - enum Cases - { - CACHING = 1, - PROCESS, - INPLACE, - - NOT_SET = 0, - NUM_Cases = INPLACE - }; - - - - template - struct SelectBuffProvider; - - template<> struct SelectBuffProvider { typedef AllocBufferFromCache Type; }; - template<> struct SelectBuffProvider { typedef AllocBufferFromParent Type; }; - template<> struct SelectBuffProvider { typedef AllocBufferFromCache Type; }; - template<> struct SelectBuffProvider<> { typedef AllocBufferFromParent Type; }; +namespace config { - - template - struct Strategy ; - using lumiera::typelist::Config; - - template - struct Strategy< Config > - : QueryCache< - AllocBufferTable< - PullInput< - AllocOutput< - ProcessData< - FeedCache< - ReleaseBuffers< - OperationBase > > > > > > > - { }; - - template - struct Strategy< Config > - : AllocBufferTable< - PullInput< - AllocOutput< - ProcessData< + /** + * Base class of all concrete invocation sequences. + * Could contain a collection of functions used to build up the invocation sequence. + * Currently contains just a marker used to detect the existence of an concrete + * definition/specialisation for a given specific configuration. + */ + class OperationBase + { + typedef lumiera::Yes_t is_defined; + + + }; + + + template + struct QueryCache : NEXT + { + BuffHandle + step (Invocation& ivo) + { + BuffHandle fetched = ivo.fetch (ivo.genFrameID()); + if (fetched) + return fetched; + else + return NEXT::step (ivo); + } + }; + + + template + struct AllocBufferTable : NEXT + { + BuffHandle + step (Invocation& ivo) + { + BuffTableChunk buffTab (ivo.wiring, ivo.getBuffTableStorage()); + ivo.setBuffTab(&buffTab); + ASSERT (ivo.buffTab); + ASSERT (ivo.buffTab_isConsistent()); + + return NEXT::step (ivo); + } + }; + + + template + struct PullInput : NEXT + { + BuffHandle + step (Invocation& ivo) + { + BuffHandle * inH = ivo.buffTab->inHandle; + BuffHandle::PBuff *inBuff = ivo.buffTab->inBuff; + + for (uint i = 0; i < ivo.nrI(); ++i ) + { + inBuff[i] = + *(inH[i] = this->pullPredecessor(ivo,i)); // invoke predecessor + // now Input #i is ready... + } + return NEXT::step (ivo); + } + }; + + + template + struct ReadSource : NEXT + { + BuffHandle + step (Invocation& ivo) + { + BuffHandle *inH = ivo.buffTab->inHandle; + BuffHandle *outH = ivo.buffTab->outHandle; + BuffHandle::PBuff *inBuff = ivo.buffTab->inBuff; + BuffHandle::PBuff *outBuff = ivo.buffTab->outBuff; + + ASSERT (ivo.nrO() == ivo.nrI() ); + + for (uint i = 0; i < ivo.nrI(); ++i ) + { + inBuff[i] = outBuff[i] = + *(inH[i] = outH[i] = this->getSource(ivo,i)); + // now Input #i is ready... + } + return NEXT::step (ivo); + } + }; + + + template + struct AllocOutput : NEXT + { + BuffHandle + step (Invocation& ivo) + { + ASSERT (ivo.buffTab); + ASSERT (ivo.nrO() < ivo.buffTabSize()); + BuffHandle *outH = ivo.buffTab->outHandle; + BuffHandle::PBuff *outBuff = ivo.buffTab->outBuff; + + for (uint i = 0; i < ivo.nrO(); ++i ) + { + outBuff[i] = + *(outH[i] = ivo.allocateBuffer (ivo.wiring.out[i].bufferType)); + // now Output buffer for channel #i is available... + } + return NEXT::step (ivo); + } + }; + + + template + struct ProcessData : NEXT + { + BuffHandle + step (Invocation& ivo) + { + ASSERT (ivo.buffTab); + ASSERT (ivo.buffTab_isConsistent()); + ASSERT (this->validateBuffers(ivo)); + + // Invoke our own process() function, + // providing the array of outBuffer+inBuffer ptrs + ivo.wiring.procFunction (ivo.buffTab->outBuff); + + return NEXT::step (ivo); + } + }; + + template + struct FeedCache : NEXT + { + BuffHandle + step (Invocation& ivo) + { + for (uint i = 0; i < ivo.nrO(); ++i ) + { + // declare all Outputs as finished + ivo.is_calculated(ivo.buffTab->outHandle[i]); + } + + return NEXT::step (ivo); + } + }; + + template + struct ReleaseBuffers : NEXT /////////////////TODO: couldn't this be done automatically by BuffTab's dtor?? + { ///////////////// this would require BuffHandle to be a smart ref.... + BuffHandle + step (Invocation& ivo) + { + // all buffers besides the required Output no longer needed + this->releaseBuffers(ivo.buffTab->outHandle, + ivo.buffTabSize(), + ivo.outNr); + + return ivo.buffTab->outHandle[ivo.outNr]; + } + }; + + + + + + /* =============================================================== */ + /* === declare the possible Assembly of these elementary steps === */ + + enum Cases + { + CACHING = 1, + PROCESS, + INPLACE, + + NOT_SET = 0, + NUM_Cases = INPLACE + }; + + + + template< char CACHE_Fl =NOT_SET + , char INPLACE_Fl =NOT_SET + > + struct SelectBuffProvider; + + template<> struct SelectBuffProvider { typedef AllocBufferFromCache Type; }; + template<> struct SelectBuffProvider { typedef AllocBufferFromParent Type; }; + template<> struct SelectBuffProvider { typedef AllocBufferFromCache Type; }; + template<> struct SelectBuffProvider<> { typedef AllocBufferFromParent Type; }; + + + template + struct Strategy ; + + using lumiera::typelist::Config; + + template + struct Strategy< Config > + : QueryCache< + AllocBufferTable< + PullInput< + AllocOutput< + ProcessData< + FeedCache< ReleaseBuffers< - OperationBase > > > > > - { }; - - template<> - struct Strategy< Config<> > - : AllocBufferTable< - ReadSource< + OperationBase > > > > > > > + { }; + + template + struct Strategy< Config > + : AllocBufferTable< + PullInput< + AllocOutput< + ProcessData< ReleaseBuffers< - OperationBase > > > - { }; - - template<> - struct Strategy< Config > : Strategy< Config<> > { }; - - template<> - struct Strategy< Config > - : AllocBufferTable< - ReadSource< - AllocOutput< - ProcessData< // wiring_.processFunction is supposed to do just buffer copying here - ReleaseBuffers< - OperationBase > > > > > - { }; - - - - - } // namespace config + OperationBase > > > > > + { }; -} // namespace engine + template<> + struct Strategy< Config<> > + : AllocBufferTable< + ReadSource< + ReleaseBuffers< + OperationBase > > > + { }; + + template<> + struct Strategy< Config > : Strategy< Config<> > { }; + + template<> + struct Strategy< Config > + : AllocBufferTable< + ReadSource< + AllocOutput< + ProcessData< // wiring_.processFunction is supposed to do just buffer copying here + ReleaseBuffers< + OperationBase > > > > > + { }; + + + + +}} // namespace engine::config #endif diff --git a/src/proc/engine/nodewiring-config.hpp b/src/proc/engine/nodewiring-config.hpp index 981c1e177..d1063f8da 100644 --- a/src/proc/engine/nodewiring-config.hpp +++ b/src/proc/engine/nodewiring-config.hpp @@ -117,7 +117,7 @@ namespace config { { FactoryHolder(PAR p) : FAC(p), - FacFunction( static_cast(*this)) + FacFunction (static_cast (*this)) { } }; @@ -127,7 +127,9 @@ namespace config { ConfigTable possibleConfig_; ///< Table of factories - /** Helper: a visitor usable with FlagInfo */ + + /** Helper: a visitor usable with FlagInfo. + * Used to create a factory for each config */ struct FactoryTableBuilder { PAR ctor_param_; @@ -153,6 +155,7 @@ namespace config { void done() {} }; + public: template ConfigSelector(CONFS const&, PAR factory_ctor_param) diff --git a/src/proc/engine/nodewiring.cpp b/src/proc/engine/nodewiring.cpp index d4b50a6cf..551566acc 100644 --- a/src/proc/engine/nodewiring.cpp +++ b/src/proc/engine/nodewiring.cpp @@ -61,6 +61,10 @@ namespace engine { + /** + * Fabricating a WiringDescriptor + * tailored for a specific node wiring situation. + */ template class WiringDescriptorFactory { @@ -138,3 +142,4 @@ namespace engine { } // namespace engine + /** preconfigured table of all possible factories */ diff --git a/tests/lib/meta/config-flags-test.cpp b/tests/lib/meta/config-flags-test.cpp index 1d11a244d..a7cbcbe13 100644 --- a/tests/lib/meta/config-flags-test.cpp +++ b/tests/lib/meta/config-flags-test.cpp @@ -230,7 +230,8 @@ namespace test { struct TestVisitor { - string result; + string result; ///< metafunction result + TestVisitor() : result ("TestVisitor application:\n") {} /* === visitation interface === */ @@ -319,7 +320,7 @@ namespace test { catch (lumiera::error::Invalid& err) { cout << err.what() << "\n"; - lumiera_error (); // reset errorflag + lumiera_error (); // reset error flag } }