From 276ac8e0826f25bc816d84ac82770b433c17afab Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 29 Jul 2008 18:03:37 +0200 Subject: [PATCH] test building a table of factories dealing with the possible configs --- src/proc/engine/nodewiringconfig.hpp | 60 +++++++++++---------- tests/common/typelist/configflagstest.cpp | 63 +++++++++++++++++++---- 2 files changed, 88 insertions(+), 35 deletions(-) diff --git a/src/proc/engine/nodewiringconfig.hpp b/src/proc/engine/nodewiringconfig.hpp index 74e987325..9223f5633 100644 --- a/src/proc/engine/nodewiringconfig.hpp +++ b/src/proc/engine/nodewiringconfig.hpp @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include /////////////////TODO: library @@ -277,16 +279,13 @@ namespace lumiera { /** * Helper for calculating values and for * invoking runtime code based on a given FlagTuple. - * Can also be used on a Typelist of several FlagTuples. + * Can also be used on a Typelist of several Configs. * The latter case is typically used to invoke an operation * while ennumerating all Flag-Configurations defined in Code. * An example would be to build (at runtime) an dispatcher table. - * Explanation: the supposed data structure is a list of lists, - * where "list" here refers to a Typelist (compile time). Each - * of the inner lists in this structure represents a single - * Flag-Configuration. For the Case covering the outer List, - * we provide a templated visitaion function, which can accept - * a functor object to be invoked on each Flag-Configuration. + * Explanation: For the Case covering a List of Configs, we provide + * a templated visitaion function, which can accept a functor object + * to be invoked on each Configuration. */ template struct FlagInfo; @@ -312,20 +311,18 @@ namespace lumiera { return functor.done(); } }; - template - struct FlagInfo, FLAGS> - , TAIL - > > + template + struct FlagInfo > { - typedef Node, FLAGS> ThisConfig; - enum{ BITS = MAX (char(FlagInfo::BITS), char(FlagInfo::BITS)) + typedef typename CONF::Flags ThisFlags; + enum{ BITS = MAX (char(FlagInfo::BITS), char(FlagInfo::BITS)) }; template static typename FUNC::Ret accept (FUNC& functor) { - functor.template visit(FlagInfo::CODE); + functor.template visit(FlagInfo::CODE); return FlagInfo::accept (functor); } }; @@ -353,6 +350,8 @@ namespace engine { using lumiera::typelist::DefineConfigByFlags; ///////TODO + using boost::lexical_cast; + using util::contains; enum Cases { @@ -404,17 +403,23 @@ namespace engine { * bulk allocation memory block -- typically for each separate * segment of the Timeline and processing node graph. * - * NOw the selection of the possible flag configurations, for which + * Now the selection of the possible flag configurations, for which * Factory instances are created in the table, is governed by the * type parameter of the ConfigSelector ctor. This type parameter * needs to be a Typelist of Typelists, each representing a flag * configuration. The intention is to to drive this selection by * the use of template metaprogramming for extracting all * currently defined StateProxy object configurations. + * @todo as the facories live only within the enclosed table (map) + * we could allocate them in-place. Unfortunately this is + * non-trivial, because the stl containers employ + * value semantics and thus do a copy even on insert. + * Thus, for now we use a shared_ptr to hold the factory + * heap allocated. */ template< template class Factory - , class PAR ///< ctor parameter of the Factories - , class RET ///< common base class of the Factory's products + , typename PAR ///< ctor parameter of the Factories + , typename RET ///< common base class of the Factory's products > class ConfigSelector { @@ -434,8 +439,8 @@ namespace engine { }; - typedef boost::scoped_ptr PFunc; - typedef std::map ConfigTable; + typedef boost::shared_ptr PFunc; + typedef std::map ConfigTable; ConfigTable possibleConfig_; ///< Table of factories @@ -454,12 +459,12 @@ namespace engine { typedef void Ret; - template + template void - visit (ulong code) + visit (size_t code) { - typedef typename DefineConfigByFlags::Config Config; - factories_[code].reset (new FactoryHolder > (ctor_param_)); + PFunc pFactory (new FactoryHolder > (ctor_param_)); + factories_[code] = pFactory; } void done() {} @@ -467,7 +472,7 @@ namespace engine { public: template - ConfigSelector(PAR factory_ctor_param) + ConfigSelector(CONFS const&, PAR factory_ctor_param) { FactoryTableBuilder buildTable(this->possibleConfig_, factory_ctor_param ); @@ -477,9 +482,12 @@ namespace engine { } RET - operator() (Bits configFlags) ///< invoke the factory corresponding to the given config + operator() (size_t configFlags) ///< invoke the factory corresponding to the given config { - return possibleConfig_[configFlags]->invoke(); + if (contains (possibleConfig_, configFlags)) + return possibleConfig_[configFlags]->invoke(); + else + throw lumiera::error::Invalid("ConfigSelector: No preconfigured factory for config-bits="+lexical_cast(configFlags)); } }; diff --git a/tests/common/typelist/configflagstest.cpp b/tests/common/typelist/configflagstest.cpp index 78584f30c..1c9dbdf83 100644 --- a/tests/common/typelist/configflagstest.cpp +++ b/tests/common/typelist/configflagstest.cpp @@ -167,8 +167,8 @@ namespace lumiera { template struct Maybe; struct Indeed { typedef Yes_t is_defined; }; - template<> struct Maybe : Indeed { enum{ CODE = 1 }; }; - template<> struct Maybe : Indeed { enum{ CODE = 3 }; }; + template<> struct Maybe : Indeed { enum{ CODE = 10 }; }; + template<> struct Maybe : Indeed { enum{ CODE = 30 }; }; template struct Maybe > @@ -204,6 +204,7 @@ namespace lumiera { check_instantiation (); check_filter (); check_FlagInfo (); + check_ConfigSelector (); } @@ -301,13 +302,12 @@ namespace lumiera { Ret done() {return result; } - template + template void visit (ulong code) { - typedef typename DefineConfigByFlags::Config Config; result += str (format ("visit(code=%u) --> %s\n") - % code % Printer::print() ); + % code % Printer::print() ); } }; @@ -323,16 +323,61 @@ namespace lumiera { cout << "max bit : " << FlagInfo::BITS <<"\n"; cout << "binary code: " << FlagInfo::CODE <<"\n"; - DISPLAY (SomeFlagsets); - cout << "max bit in [SomeFlagsets] : " << FlagInfo::BITS <<"\n"; + typedef Apply SomeConfigs; + DISPLAY (SomeConfigs); + cout << "max bit in [SomeConfigs] : " << FlagInfo::BITS <<"\n"; TestVisitor visitor; - cout << FlagInfo::accept (visitor); + cout << FlagInfo::accept (visitor); } - void check_Factory() + template + struct TestFactory + { + uint operator() () { return offset_ + Maybe::CODE; } + TestFactory(long o) : offset_(o) {} + + private: + long offset_; + }; + + + void check_ConfigSelector() { + cout << "\n==== check_ConfigSelector()\n"; + + typedef Apply ListAllConfigs; + typedef Filter::Test> Possible_Configs; + DISPLAY (Possible_Configs); + + typedef engine::ConfigSelector TestFactorySelector; + + const long offset = 1000; // parameter fed to all TestFactory ctors + TestFactorySelector testConfigSelector (Possible_Configs::List(), offset); + + + #define INVOKE_CONFIG_SELECTOR(CODE) \ + cout << " Flag-code = " << CODE \ + << " ConfigSelector() ---> " \ + << testConfigSelector (CODE) << "\n"; + + INVOKE_CONFIG_SELECTOR (2); + INVOKE_CONFIG_SELECTOR (12); + INVOKE_CONFIG_SELECTOR (20); + INVOKE_CONFIG_SELECTOR (4); + INVOKE_CONFIG_SELECTOR (8); + + try + { + INVOKE_CONFIG_SELECTOR (23); + NOTREACHED ; + } + catch (lumiera::error::Invalid& err) + { + cout << err.what() << "\n"; + lumiera_error (); // reset errorflag + } }