From 4fd301860f079b5271a844ab9a0535c6920a8977 Mon Sep 17 00:00:00 2001 From: Markus Frank Date: Mon, 21 Nov 2022 15:42:01 +0100 Subject: [PATCH] Simplify and fix late grammars in component properties --- DDCore/include/DD4hep/ComponentProperties.h | 75 ++++----------------- DDCore/include/DD4hep/Grammar.h | 1 + DDCore/include/DD4hep/GrammarParsed.h | 22 ++++-- DDCore/src/ComponentProperties.cpp | 49 +------------- DDCore/src/Grammar.cpp | 49 ++++++++++++-- DDCore/src/PropertyDictionary.h | 2 - DDG4/include/DDG4/Geant4Action.h | 3 - DDG4/src/Geant4Action.cpp | 6 -- examples/DDDigi/scripts/TestFramework.py | 22 +++--- 9 files changed, 86 insertions(+), 143 deletions(-) diff --git a/DDCore/include/DD4hep/ComponentProperties.h b/DDCore/include/DD4hep/ComponentProperties.h index cce28c8b7..04eed6509 100644 --- a/DDCore/include/DD4hep/ComponentProperties.h +++ b/DDCore/include/DD4hep/ComponentProperties.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -29,53 +30,6 @@ namespace dd4hep { class Property; class BasicGrammar; - class PropertyGrammar; - - /// Interface class to configure properties in components - /** - * Placeholder interface. - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_CORE - */ - class PropertyConfigurator { - protected: - /// Default destructor - virtual ~PropertyConfigurator(); - public: - virtual void set(const PropertyGrammar& setter, const std::string&, const std::string&, void* ptr) const = 0; - }; - - - /// Class describing the grammar representation of a given data type - /** - * Note: This class cannot be saved to a ROOT file! - * - * \author M.Frank - * \version 1.0 - * \ingroup DD4HEP_CORE - */ - class PropertyGrammar { - protected: - friend class Property; - const BasicGrammar& m_grammar; //! This member is not ROOT persistent as the entire class is not. - public: - /// Default constructor - PropertyGrammar(const BasicGrammar& g); - /// Default destructor - virtual ~PropertyGrammar(); - /// Error callback on invalid conversion - static void invalidConversion(const std::type_info& from, const std::type_info& to); - /// Error callback on invalid conversion - static void invalidConversion(const std::string& value, const std::type_info& to); - /// Access to the type information - virtual const std::type_info& type() const; - /// Serialize an opaque value to a string - virtual std::string str(const void* ptr) const; - /// Set value from serialized string. On successful data conversion TRUE is returned. - virtual bool fromString(void* ptr, const std::string& value) const; - }; /// The property class to assign options to actions. /** @@ -94,9 +48,9 @@ namespace dd4hep { class Property { protected: /// Pointer to the data location - void* m_par = 0; + void* m_par { nullptr }; /// Reference to the grammar of this property (extended type description) - const PropertyGrammar* m_hdl = 0; + const BasicGrammar* m_hdl { nullptr }; public: /// Default constructor @@ -114,7 +68,7 @@ namespace dd4hep { /// Property type name std::string type() const; /// Access grammar object - const PropertyGrammar& grammar() const; + const BasicGrammar& grammar() const; /// Conversion to string value std::string str() const; /// Conversion from string value @@ -138,18 +92,19 @@ namespace dd4hep { }; /// User constructor - template Property::Property(TYPE& val) : m_par(&val), m_hdl(0) { - static PropertyGrammar grammar(BasicGrammar::instance()); - m_hdl = &grammar; - } + template Property::Property(TYPE& val) + : m_par(&val), m_hdl(0) + { + m_hdl = &BasicGrammar::get(typeid(TYPE)); + } /// Set value of this property template void Property::set(const TYPE& val) { - const PropertyGrammar& grm = grammar(); + const auto& grm = grammar(); if (grm.type() == typeid(TYPE)) *(TYPE*) m_par = val; else if (!grm.fromString(m_par, BasicGrammar::instance< TYPE >().str(&val))) - PropertyGrammar::invalidConversion(typeid(TYPE), grm.type()); + BasicGrammar::invalidConversion(typeid(TYPE), grm.type()); } /// Assignment operator / set new balue @@ -160,11 +115,11 @@ namespace dd4hep { /// Retrieve value from stack (large values e.g. vectors etc.) template void Property::value(TYPE& val) const { - const PropertyGrammar& grm = grammar(); + const auto& grm = grammar(); if (grm.type() == typeid(TYPE)) val = *(TYPE*) m_par; else if (!BasicGrammar::instance< TYPE >().fromString(&val, this->str())) - PropertyGrammar::invalidConversion(grm.type(), typeid(TYPE)); + BasicGrammar::invalidConversion(grm.type(), typeid(TYPE)); } /// Retrieve value @@ -196,7 +151,7 @@ namespace dd4hep { /// Equality operator bool operator==(const TYPE& val) const { return val == data; } /// Access grammar object - const PropertyGrammar& grammar() const { return this->Property::grammar(); } + const BasicGrammar& grammar() const { return this->Property::grammar(); } /// Conversion to string value std::string str() const { return this->Property::str(); } /// Retrieve value with data conversion @@ -258,8 +213,6 @@ namespace dd4hep { template void add(const std::string& name, T& value) { add(name, Property(value)); } - /// Bulk set of all properties - void set(const std::string& component_name, PropertyConfigurator& setup); /// Apply functor on properties template void for_each(FUNCTOR& func) { std::for_each(m_properties.begin(), m_properties.end(), func); diff --git a/DDCore/include/DD4hep/Grammar.h b/DDCore/include/DD4hep/Grammar.h index 535497984..f60bae044 100644 --- a/DDCore/include/DD4hep/Grammar.h +++ b/DDCore/include/DD4hep/Grammar.h @@ -27,6 +27,7 @@ // C/C++ include files #include +#include #include // Forward declarations diff --git a/DDCore/include/DD4hep/GrammarParsed.h b/DDCore/include/DD4hep/GrammarParsed.h index d348bf60e..d74dd6662 100644 --- a/DDCore/include/DD4hep/GrammarParsed.h +++ b/DDCore/include/DD4hep/GrammarParsed.h @@ -54,17 +54,27 @@ namespace dd4hep { std::pair grammar_evaluate_item(std::string val); /// PropertyGrammar overload: Retrieve value from string - template bool grammar_fromString(const BasicGrammar& gr, void* ptr, const std::string& string_val) { + template bool grammar_fromString(const BasicGrammar& gr, void* ptr, const std::string& val) { int sc = 0; TYPE temp; try { - sc = ::dd4hep::Parsers::parse(temp,string_val); +#ifdef DD4HEP_DEBUG_PROPERTIES + std::cout << "Parsing " << val << std::endl; +#endif + sc = ::dd4hep::Parsers::parse(temp, val); + if ( sc ) { + *(TYPE*)ptr = temp; + return true; + } } catch (...) { } - if ( !sc ) sc = gr.evaluate(&temp,string_val); -#if 0 - std::cout << "Sc=" << sc << " Converting value: " << string_val +#ifdef DD4HEP_DEBUG_PROPERTIES + std::cout << "Parsing " << val << "FAILED" << std::endl; +#endif + if ( !sc ) sc = gr.evaluate(&temp,val); +#ifdef DD4HEP_DEBUG_PROPERTIES + std::cout << "Sc=" << sc << " Converting value: " << val << " to type " << typeid(TYPE).name() << std::endl; #endif @@ -72,7 +82,7 @@ namespace dd4hep { *(TYPE*)ptr = temp; return true; } - BasicGrammar::invalidConversion(string_val, typeid(TYPE)); + BasicGrammar::invalidConversion(val, typeid(TYPE)); return false; } diff --git a/DDCore/src/ComponentProperties.cpp b/DDCore/src/ComponentProperties.cpp index 867c314d0..429e2b2f2 100644 --- a/DDCore/src/ComponentProperties.cpp +++ b/DDCore/src/ComponentProperties.cpp @@ -24,47 +24,6 @@ using namespace std; using namespace dd4hep; -/// Default destructor -PropertyConfigurator::~PropertyConfigurator() { -} - -/// Default constructor -PropertyGrammar::PropertyGrammar(const BasicGrammar& g) : m_grammar(g) { -} - -/// Default destructor -PropertyGrammar::~PropertyGrammar() { -} - -/// Error callback on invalid conversion -void PropertyGrammar::invalidConversion(const std::type_info& from, - const std::type_info& to) -{ - BasicGrammar::invalidConversion(from,to); -} - -/// Error callback on invalid conversion -void PropertyGrammar::invalidConversion(const std::string& value, - const std::type_info& to) -{ - BasicGrammar::invalidConversion(value,to); -} - -/// Access to the type information -const std::type_info& PropertyGrammar::type() const { - return m_grammar.type(); -} - -/// Serialize an opaque value to a string -std::string PropertyGrammar::str(const void* ptr) const { - return m_grammar.str(ptr); -} - -/// Set value from serialized string. On successful data conversion TRUE is returned. -bool PropertyGrammar::fromString(void* ptr, const std::string& value) const { - return m_grammar.fromString(ptr,value); -} - /// Property type name string Property::type(const Property& property) { return type(property.grammar().type()); @@ -80,7 +39,7 @@ string Property::type() const { return Property::type(grammar().type()); } -const PropertyGrammar& Property::grammar() const { +const BasicGrammar& Property::grammar() const { if ( m_hdl ) return *m_hdl; throw runtime_error("Attempt to access property grammar from invalid object."); @@ -198,12 +157,6 @@ void PropertyManager::add(const string& name, const Property& prop) { m_properties.emplace(name, prop); } -/// Bulk set of all properties -void PropertyManager::set(const string& component_name, PropertyConfigurator& cfg) { - for (auto& i : m_properties ) - cfg.set(i.second.grammar(), component_name, i.first, i.second.ptr()); -} - /// Dump string values void PropertyManager::dump() const { for (const auto& i : m_properties ) diff --git a/DDCore/src/Grammar.cpp b/DDCore/src/Grammar.cpp index c89593da8..12a6498c0 100644 --- a/DDCore/src/Grammar.cpp +++ b/DDCore/src/Grammar.cpp @@ -91,7 +91,6 @@ namespace dd4hep { } } - /// Equality operator bool dd4hep::BasicGrammar::specialization_t::operator==(const specialization_t& cp) const { return this->bind == cp.bind && @@ -115,31 +114,68 @@ dd4hep::BasicGrammar::BasicGrammar(const std::string& typ) /// Default destructor dd4hep::BasicGrammar::~BasicGrammar() { } - +#include /// Prenote loadable grammar void dd4hep::BasicGrammar::pre_note(const std::type_info& info, const BasicGrammar& (*fcn)(), specialization_t specs) { key_type hash = dd4hep::detail::hash64(typeName(info)); +#ifdef DD4HEP_DEBUG_PROPERTIES + std::cout << "pre_note(1) " << typeName(info) + << " " << (void*)specs.str + << " " << (void*)specs.fromString + << std::endl; +#endif if ( !prenote_registry().emplace(hash, std::make_pair(fcn,specs)).second ) { auto j = prenote_registry().find(hash); const auto& entry = (*j).second; +#ifdef DD4HEP_DEBUG_PROPERTIES + const auto& gramm = entry.first(); + std::cout << "pre_note(2) " << typeName(info) + << " " << (void*)gramm.specialization.fromString + << " " << (void*)entry.second.fromString + << std::endl; +#endif if ( !(entry.first == fcn && entry.second == specs) ) { // Error: Already existing grammar. dd4hep::except("BasicGrammar","FAILED to add existent registry: %s [%016llX]", typeName(info).c_str(), hash); } } + /// If the grammer was instantiated before the pre-note: update the grammar... + auto i = active_registry().find(hash); + if ( i != active_registry().end() ) { + i->second->specialization = specs; + } } /// Lookup existing grammar using hash code (reading objects) const dd4hep::BasicGrammar& dd4hep::BasicGrammar::get(key_type hash) { auto i = active_registry().find(hash); - if ( i != active_registry().end() ) + if ( i != active_registry().end() ) { +#ifdef DD4HEP_DEBUG_PROPERTIES + const auto& entry = (*i).second; + const auto& gramm = *entry; + std::cout << "get(1) " << hash + << " grammar: " << (void*)&gramm + << " " << (void*)gramm.specialization.fromString + << " " << (void*)entry->specialization.fromString + << std::endl; +#endif return *(i->second); + } auto j = prenote_registry().find(hash); - if ( j != prenote_registry().end() ) + if ( j != prenote_registry().end() ) { +#ifdef DD4HEP_DEBUG_PROPERTIES + const auto& entry = (*j).second; + const auto& gramm = entry.first(); + std::cout << "get(2) " << hash + << " " << (void*)gramm.specialization.fromString + << " " << (void*)entry.second.fromString + << std::endl; +#endif return (j->second.first)(); + } dd4hep::except("BasicGrammar","FAILED to look up non existent registry: %016llX",hash); throw "Error"; // Not reachable anyhow. Simply to please the compiler! } @@ -232,8 +268,9 @@ std::string dd4hep::BasicGrammar::str(const void* ptr) const { /// Set value from serialized string. On successful data conversion TRUE is returned. bool dd4hep::BasicGrammar::fromString(void* ptr, const std::string& value) const { if ( specialization.fromString ) - return specialization.fromString(*this,ptr, value); - except("Grammar", "Cannot deserialize object with incomplete grammar: %s", type_name().c_str()); + return specialization.fromString(*this, ptr, value); + except("Grammar", "Cannot deserialize object with incomplete grammar: %s [%s] %p fromString: %s", + type_name().c_str(), this->name.c_str(), (void*)this, (void*)specialization.fromString); return false; } diff --git a/DDCore/src/PropertyDictionary.h b/DDCore/src/PropertyDictionary.h index 03d49d8f6..7a7ce2b54 100644 --- a/DDCore/src/PropertyDictionary.h +++ b/DDCore/src/PropertyDictionary.h @@ -147,8 +147,6 @@ template class std::map; #pragma link C++ class std::map-; #pragma link C++ class dd4hep::PropertyManager-; #pragma link C++ class dd4hep::PropertyConfigurable-; -#pragma link C++ class dd4hep::PropertyConfigurator-; -#pragma link C++ class dd4hep::PropertyGrammar-; #endif // __CINT__ #endif // DDCORE_SRC_PROPERTYDICTIONARY_H diff --git a/DDG4/include/DDG4/Geant4Action.h b/DDG4/include/DDG4/Geant4Action.h index a4bdcdf5b..289aed8e6 100644 --- a/DDG4/include/DDG4/Geant4Action.h +++ b/DDG4/include/DDG4/Geant4Action.h @@ -308,9 +308,6 @@ namespace dd4hep { bool hasProperty(const std::string& name) const; /// Access single property Property& property(const std::string& name); - /// Set object properties - Geant4Action& setProperties(PropertyConfigurator& setup); - /// Install property control messenger if wanted virtual void installMessengers(); /// Install command control messenger if wanted diff --git a/DDG4/src/Geant4Action.cpp b/DDG4/src/Geant4Action.cpp index b1a810adb..2b7660298 100644 --- a/DDG4/src/Geant4Action.cpp +++ b/DDG4/src/Geant4Action.cpp @@ -93,12 +93,6 @@ PrintLevel Geant4Action::setOutputLevel(PrintLevel new_level) { return (PrintLevel)old; } -/// Set object properties -Geant4Action& Geant4Action::setProperties(PropertyConfigurator& setup) { - m_properties.set(m_name, setup); - return *this; -} - /// Check property for existence bool Geant4Action::hasProperty(const string& nam) const { return m_properties.exists(nam); diff --git a/examples/DDDigi/scripts/TestFramework.py b/examples/DDDigi/scripts/TestFramework.py index 7703989b4..d34b66f50 100644 --- a/examples/DDDigi/scripts/TestFramework.py +++ b/examples/DDDigi/scripts/TestFramework.py @@ -14,10 +14,10 @@ def make_input(kernel): - input_1 = dddigi.TestAction(kernel, 'input_01', 100) - input_2 = dddigi.TestAction(kernel, 'input_02', 200) - input_3 = dddigi.TestAction(kernel, 'input_03', 150) - input_4 = dddigi.TestAction(kernel, 'input_04', 60) + input_1 = dddigi.TestAction(kernel, 'input_01', 50) + input_2 = dddigi.TestAction(kernel, 'input_02', 100) + input_3 = dddigi.TestAction(kernel, 'input_03', 75) + input_4 = dddigi.TestAction(kernel, 'input_04', 30) seq = kernel.inputAction() seq.adopt(input_1) seq.adopt(input_2) @@ -27,11 +27,11 @@ def make_input(kernel): def make_subdetector(kernel, name): - action_1 = dddigi.TestAction(kernel, name + '_deposits', 150) - action_2 = dddigi.TestAction(kernel, name + '_rndmNoise', 100) - action_3 = dddigi.TestAction(kernel, name + '_deadChan', 100) - action_4 = dddigi.TestAction(kernel, name + '_noiseChan', 50) - action_5 = dddigi.TestAction(kernel, name + '_merge', 200) + action_1 = dddigi.TestAction(kernel, name + '_deposits', 75) + action_2 = dddigi.TestAction(kernel, name + '_rndmNoise', 50) + action_3 = dddigi.TestAction(kernel, name + '_deadChan', 50) + action_4 = dddigi.TestAction(kernel, name + '_noiseChan', 25) + action_5 = dddigi.TestAction(kernel, name + '_merge', 60) seq = dddigi.Action(kernel, 'DigiActionSequence/' + name + '_sequence', parallel=True) seq.adopt(action_1) seq.adopt(action_2) @@ -63,12 +63,12 @@ def run(): event_processor.adopt(seq) kernel.eventAction().adopt(event_processor) # Output - output = dddigi.TestAction(kernel, 'output_01', 200) + output = dddigi.TestAction(kernel, 'output_01', 50) kernel.outputAction().adopt(output) dddigi.setPrintLevel(dddigi.OutputLevel.DEBUG) kernel.numThreads = 0 # = number of concurrent threads - kernel.numEvents = 10 + kernel.numEvents = 5 kernel.maxEventsParallel = 3 kernel.run() dddigi.setPrintLevel(dddigi.OutputLevel.INFO)