diff --git a/DDCore/include/DD4hep/Conditions.h b/DDCore/include/DD4hep/Conditions.h index 0c7fcd697af8e3b4daf2c869ecd829e935e4be3d..3a0f021a99c9c996f6c6476b6fcedde7eb292a53 100644 --- a/DDCore/include/DD4hep/Conditions.h +++ b/DDCore/include/DD4hep/Conditions.h @@ -212,7 +212,7 @@ namespace dd4hep { * Note: The type definition is possible exactly once. * Any further rebindings MUST match the identical type. */ - template <typename T, typename... Args> T& construct(Args&&... args); + template <typename T, typename... Args> T& construct(Args... args); /** Bind the data of the conditions object to a given format. * * Note: The type definition is possible exactly once. @@ -240,7 +240,7 @@ namespace dd4hep { : Handle<Condition::Object>(e) {} /// Construct conditions object and bind the data - template <typename T, typename... Args> T& Condition::construct(Args&&... args) { + template <typename T, typename... Args> T& Condition::construct(Args... args) { return data().construct<T,Args...>(args...); } /// Bind the data of the conditions object to a given format. diff --git a/DDCore/include/DD4hep/DD4hepRootPersistency.h b/DDCore/include/DD4hep/DD4hepRootPersistency.h index 4cf76f316300e7a34beea53d9c70b74911b72919..9a77db986f9b8cdfb4883fb180b5336c71dc25ff 100644 --- a/DDCore/include/DD4hep/DD4hepRootPersistency.h +++ b/DDCore/include/DD4hep/DD4hepRootPersistency.h @@ -16,6 +16,7 @@ // Framework include files #include "DD4hep/DetectorData.h" + /// Helper class to support ROOT persistency of Detector objects /** * \author M.Frank @@ -34,9 +35,10 @@ public: std::map<dd4hep::DetElement,dd4hep::AlignmentCondition> nominals; /// Default constructor - DD4hepRootPersistency() : TNamed() {} + DD4hepRootPersistency(); + /// Default destructor - virtual ~DD4hepRootPersistency() {} + virtual ~DD4hepRootPersistency(); /// Save an existing detector description in memory to a ROOT file static int save(dd4hep::Detector& description, const char* fname, const char* instance = "Geometry"); @@ -88,6 +90,7 @@ public: ClassDef(DD4hepRootPersistency,1); }; + /// Helper class to check various ingredients of the Detector object after loaded from ROOT /** * \author M.Frank diff --git a/DDCore/include/DD4hep/Grammar.h b/DDCore/include/DD4hep/Grammar.h index 2c2f0f5f1a7da416f50040bffb3dbca86e028396..941ae401c983ea4d26470bbf59a2485820d24998 100644 --- a/DDCore/include/DD4hep/Grammar.h +++ b/DDCore/include/DD4hep/Grammar.h @@ -66,6 +66,13 @@ namespace dd4hep { mutable int root_data_type = -1; /// Initialization flag mutable bool inited = false; + /// Structure to be filled if automatic object parsing from string is supposed to be supported + struct specialization_t { + /// Bind opaque address to object + void (*bind)(void* pointer) = 0; + /// Opaque copy constructor + void (*copy)(void* to, const void* from) = 0; + } specialization; protected: /// Default constructor @@ -81,12 +88,13 @@ namespace dd4hep { /// Instance factory - static void pre_note(const std::type_info& info, const BasicGrammar& (*fcn)()); - static const BasicGrammar& get(const std::type_info& info); + static void pre_note(const std::type_info& info, const BasicGrammar& (*fcn)(), specialization_t specs); public: /// Instance factory template <typename TYPE> static const BasicGrammar& instance(); + /// Access grammar by type info + static const BasicGrammar& get(const std::type_info& info); /// Lookup existing grammar using the grammar's hash code/hash64(type-name) (used for reading objects) static const BasicGrammar& get(unsigned long long int hash_code); /// Error callback on invalid conversion @@ -113,13 +121,8 @@ namespace dd4hep { virtual const std::type_info& type() const = 0; /// Access the object size (sizeof operator) virtual size_t sizeOf() const = 0; - /// Opaque copy constructor - virtual void copy(void* to, const void* from) const = 0; /// Opaque object destructor virtual void destruct(void* pointer) const = 0; - - /// Bind opaque address to object - virtual void bind(void* pointer) const = 0; /// Serialize an opaque value to a string virtual std::string str(const void* ptr) const = 0; /// Set value from serialized string. On successful data conversion TRUE is returned. @@ -142,7 +145,8 @@ namespace dd4hep { Grammar(); public: - + typedef TYPE type_t; + /** Base class overrides */ /// PropertyGrammar overload: Access to the type information virtual const std::type_info& type() const override; @@ -150,12 +154,10 @@ namespace dd4hep { virtual bool equals(const std::type_info& other_type) const override; /// Access the object size (sizeof operator) virtual size_t sizeOf() const override; - /// Opaque copy constructor - virtual void copy(void* to, const void* from) const override; /// Opaque object destructor virtual void destruct(void* pointer) const override; /// Bind opaque address to object - virtual void bind(void* pointer) const override; + template <typename... Args> void construct(void* pointer, Args... args) const; /// PropertyGrammar overload: Serialize a property to a string virtual std::string str(const void* ptr) const override; /// PropertyGrammar overload: Retrieve value from string @@ -167,7 +169,9 @@ namespace dd4hep { }; /// Standarsd constructor - template <typename TYPE> Grammar<TYPE>::Grammar() : BasicGrammar(typeName(typeid(TYPE))) { + template <typename TYPE> Grammar<TYPE>::Grammar() + : BasicGrammar(typeName(typeid(TYPE))) + { } /// Default destructor @@ -194,16 +198,10 @@ namespace dd4hep { TYPE* obj = (TYPE*)pointer; obj->~TYPE(); } - - /// Opaque copy constructor - template <typename TYPE> void Grammar<TYPE>::copy(void* to, const void* from) const { - const TYPE* from_obj = (const TYPE*)from; - new (to) TYPE(*from_obj); - } - /// Bind opaque address to object - template <typename TYPE> void Grammar<TYPE>::bind(void* pointer) const { - new(pointer) TYPE(); + template <typename TYPE> template <typename... Args> + void Grammar<TYPE>::construct(void* pointer, Args... args) const { + new(pointer) TYPE(std::forward<Args>(args)...); } /// Grammar registry interface @@ -218,7 +216,8 @@ namespace dd4hep { public: /// Registry instance singleton static const GrammarRegistry& instance(); - template <typename T> static const GrammarRegistry& pre_note() { + + template <typename T> static const GrammarRegistry& pre_note_specs(BasicGrammar::specialization_t specs) { // Apple (or clang) wants this.... std::string (Grammar<T>::*str)(const void*) const = &Grammar<T>::str; bool (Grammar<T>::*fromString)(void*, const std::string&) const = &Grammar<T>::fromString; @@ -226,10 +225,18 @@ namespace dd4hep { if ( !(fromString && str && evaluate) ) { BasicGrammar::invalidConversion("Grammar",typeid(T)); } - BasicGrammar::pre_note(typeid(T),BasicGrammar::instance<T>); + BasicGrammar::pre_note(typeid(T), BasicGrammar::instance<T>, specs); return instance(); } + template <typename T> static const GrammarRegistry& pre_note(int) { + BasicGrammar::specialization_t spec; + spec.bind = detail::constructObject<T>; + spec.copy = detail::copyObject<T>; + return pre_note_specs<T>(spec); + } + template <typename T> static const GrammarRegistry& pre_note() { + return pre_note_specs<T>({}); + } }; - } #endif /* DD4HEP_DDCORE_DETAIL_GRAMMAR_H */ diff --git a/DDCore/include/DD4hep/OpaqueData.h b/DDCore/include/DD4hep/OpaqueData.h index 223d96b98900fe3b9bf897810aee18f3a06aa8df..194fb61da26272a776d94a20a04645bf48d8353a 100644 --- a/DDCore/include/DD4hep/OpaqueData.h +++ b/DDCore/include/DD4hep/OpaqueData.h @@ -123,7 +123,7 @@ namespace dd4hep { /// Bind data value in place void* bind(void* ptr, size_t len, const BasicGrammar* grammar); /// Construct conditions object and bind the data - template <typename T, typename... Args> T& construct(Args&&... args); + template <typename T, typename... Args> T& construct(Args... args); /// Bind data value template <typename T> T& bind(); /// Bind data value @@ -147,7 +147,7 @@ namespace dd4hep { } /// Construct conditions object and bind the data - template <typename T, typename... Args> T& OpaqueDataBlock::construct(Args&&... args) { + template <typename T, typename... Args> T& OpaqueDataBlock::construct(Args... args) { this->bind(&BasicGrammar::instance<T>()); return *(new(this->pointer) T(std::forward<Args>(args)...)); } diff --git a/DDCore/include/DD4hep/detail/Grammar_parsed.h b/DDCore/include/DD4hep/detail/Grammar_parsed.h index 0a02b79c2cab71291a5a94e0c7528d95ae04066b..1a0d2bcf7fef836b21465ebff81b50af81d2be4e 100644 --- a/DDCore/include/DD4hep/detail/Grammar_parsed.h +++ b/DDCore/include/DD4hep/detail/Grammar_parsed.h @@ -224,8 +224,15 @@ namespace dd4hep { /// Standarsd constructor template <typename TYPE> const BasicGrammar& BasicGrammar::instance() { - static Grammar<TYPE> s_gr; - return s_gr; + static Grammar<TYPE> *s_gr = 0; + if ( 0 != s_gr ) { + return *s_gr; + } + static Grammar<TYPE> gr; + if ( 0 == gr.specialization.bind ) gr.specialization.bind = detail::constructObject<TYPE>; + if ( 0 == gr.specialization.copy ) gr.specialization.copy = detail::copyObject<TYPE>; + s_gr = &gr; + return *s_gr; } } // End namespace dd4hep diff --git a/DDCore/include/DD4hep/detail/Grammar_unparsed.h b/DDCore/include/DD4hep/detail/Grammar_unparsed.h index c820a09203bade1e94e783970e4d1700cb53665e..f7e3058290169be4f846ffa35fb38eea4e55d62a 100644 --- a/DDCore/include/DD4hep/detail/Grammar_unparsed.h +++ b/DDCore/include/DD4hep/detail/Grammar_unparsed.h @@ -23,24 +23,29 @@ // Framework include files #include "DD4hep/Grammar.h" +#include "DD4hep/Printout.h" /// Namespace for the AIDA detector description toolkit namespace dd4hep { + /// PropertyGrammar overload: Retrieve value from string template <typename TYPE> bool Grammar<TYPE>::fromString(void* /*ptr*/, const std::string& /*val*/) const { return true; } - /// Serialize a property to a string + + /// Serialize a property to a string template <typename TYPE> std::string Grammar<TYPE>::str(const void* /*ptr*/) const { return ""; } + /// Evaluate string value if possible before calling boost::spirit template <typename TYPE> int Grammar<TYPE>::evaluate(void*, const std::string&) const { return 0; } + /// Standarsd constructor template <typename TYPE> const BasicGrammar& BasicGrammar::instance() { - static Grammar<TYPE> s_gr; + static Grammar<TYPE> s_gr(); return s_gr; } } diff --git a/DDCore/include/Parsers/Primitives.h b/DDCore/include/Parsers/Primitives.h index c91f3a8e595faf1e3f6f3f476a13ed3d0e11a429..a1757807cdadabf636c3c9f05f0f8aa173f07192 100644 --- a/DDCore/include/Parsers/Primitives.h +++ b/DDCore/include/Parsers/Primitives.h @@ -311,6 +311,10 @@ namespace dd4hep { const T* src = (const T*)source; ::new(target) T(*src); } + /// Helper to copy objects. + template <typename T> inline void constructObject(void* target) { + ::new(target) T(); + } /// Helper to destruct objects. Note: The memory is NOT released! template <typename T> inline void destructObject(T* ptr) { ptr->~T(); diff --git a/DDCore/python/dd4hep_base.py b/DDCore/python/dd4hep_base.py index f633524c71313a886ece7b75da482ccfa20d6168..a1cfa60557282d877f88aa3fbd70541b92b7e7db 100644 --- a/DDCore/python/dd4hep_base.py +++ b/DDCore/python/dd4hep_base.py @@ -111,23 +111,27 @@ std_list = std.list std_map = std.map std_pair = std.pair # --------------------------------------------------------------------------- -core = dd4hep -cond = dd4hep.cond -tools = dd4hep.tools -align = dd4hep.align +core = dd4hep +cond = dd4hep.cond +tools = dd4hep.tools +align = dd4hep.align detail = dd4hep.detail -units = imp.new_module('units') +units = imp.new_module('units') # --------------------------------------------------------------------------- import_namespace_item('tools', 'Evaluator') # --------------------------------------------------------------------------- import_namespace_item('core', 'NamedObject') import_namespace_item('core', 'run_interpreter') - +# +import_namespace_item('detail', 'interp') +import_namespace_item('detail', 'eval') +#def run_interpreter(name): detail.interp.run(name) +#def evaluator(): return eval.instance() +#def g4Evaluator(): return eval.g4instance() def import_detail(): import_namespace_item('detail', 'DD4hepUI') - def import_geometry(): import_namespace_item('core', 'setPrintLevel') import_namespace_item('core', 'setPrintFormat') @@ -198,7 +202,6 @@ def import_geometry(): import_namespace_item('core', 'UnionSolid') import_namespace_item('core', 'IntersectionSolid') - def import_tgeo(): import_root('TGeoManager') import_root('TGeoNode') diff --git a/DDCore/src/AlignmentData.cpp b/DDCore/src/AlignmentData.cpp index bcc20e14b4aee5538938d41afeab7a704014933b..1b8d07f8116a378c3d4e917194d04ced34dc9654 100644 --- a/DDCore/src/AlignmentData.cpp +++ b/DDCore/src/AlignmentData.cpp @@ -230,7 +230,6 @@ Alignment AlignmentData::nominal() const { } #include "DD4hep/detail/Grammar_unparsed.h" -// Ensure the grammars are registered and instantiated -static auto s_registry = GrammarRegistry::pre_note<Delta>() - .pre_note<AlignmentData>() - .pre_note<std::map<DetElement, Delta> >(); +static auto s_registry = GrammarRegistry::pre_note<Delta>(1) + .pre_note<AlignmentData>(1) + .pre_note<std::map<DetElement, Delta> >(1); diff --git a/DDCore/src/AlignmentsCalculator.cpp b/DDCore/src/AlignmentsCalculator.cpp index bc93b0fe13baa2ebef796d144faca547408d5cc5..5f058888d12485d42aa7fa3db908e7a674afbec2 100644 --- a/DDCore/src/AlignmentsCalculator.cpp +++ b/DDCore/src/AlignmentsCalculator.cpp @@ -324,5 +324,4 @@ size_t AlignmentsCalculator::extract_deltas(DetElement start, } #include "DD4hep/detail/Grammar_unparsed.h" -// Ensure the grammars are registered and instantiated -static auto s_registry = GrammarRegistry::pre_note<AlignmentsCalculator::OrderedDeltas>(); +static auto s_registry = GrammarRegistry::pre_note<AlignmentsCalculator::OrderedDeltas>(1); diff --git a/DDCore/src/AlignmentsInterna.cpp b/DDCore/src/AlignmentsInterna.cpp index 933157a4b637ac19eae87d8a4af2b0c790e84d6c..7d1ed75853b07017ce5272c110634ce592eaa46f 100644 --- a/DDCore/src/AlignmentsInterna.cpp +++ b/DDCore/src/AlignmentsInterna.cpp @@ -68,6 +68,4 @@ void AlignmentObject::clear() { } #include "DD4hep/detail/Grammar_unparsed.h" -namespace dd4hep { - //template const BasicGrammar& BasicGrammar::instance<AlignmentObject>(); -} +static auto s_registry = GrammarRegistry::pre_note<AlignmentObject>(); diff --git a/DDCore/src/ComponentProperties.cpp b/DDCore/src/ComponentProperties.cpp index 16ff9c98c4db40eda2bbc71b23037702d6978bf1..04ac044943a2556b3d46345df81ffdbd68fe11f3 100644 --- a/DDCore/src/ComponentProperties.cpp +++ b/DDCore/src/ComponentProperties.cpp @@ -245,6 +245,6 @@ namespace dd4hep { } // Ensure the grammars are registered template class Grammar<Property>; - static auto s_registry = GrammarRegistry::pre_note<Property>(); + static auto s_registry = GrammarRegistry::pre_note<Property>(1); } diff --git a/DDCore/src/ConditionsData.cpp b/DDCore/src/ConditionsData.cpp index ebabba8bceb6e32df9bffe28e912352b3c3fb15f..69666c8e66f225185820df1701043635d662ea23 100644 --- a/DDCore/src/ConditionsData.cpp +++ b/DDCore/src/ConditionsData.cpp @@ -77,5 +77,4 @@ AbstractMap& AbstractMap::operator=(const AbstractMap& c) { } #include "DD4hep/detail/Grammar_unparsed.h" -// Ensure the grammars are registered and instantiated -static auto s_registry = dd4hep::GrammarRegistry::pre_note<AbstractMap>(); +static auto s_registry = dd4hep::GrammarRegistry::pre_note<AbstractMap>(1); diff --git a/DDCore/src/DD4hepRootPersistency.cpp b/DDCore/src/DD4hepRootPersistency.cpp index 90ca4f7d5007a1c9e8584beec6a0cb816dc31fb4..9e9ebc5f769b4803781850d5c8e5b2c541d51178 100644 --- a/DDCore/src/DD4hepRootPersistency.cpp +++ b/DDCore/src/DD4hepRootPersistency.cpp @@ -27,6 +27,14 @@ ClassImp(DD4hepRootPersistency) using namespace dd4hep; using namespace std; +/// Default constructor +DD4hepRootPersistency::DD4hepRootPersistency() : TNamed() { +} + +/// Default destructor +DD4hepRootPersistency::~DD4hepRootPersistency() { +} + int DD4hepRootPersistency::save(Detector& description, const char* fname, const char* instance) { TFile* f = TFile::Open(fname,"RECREATE"); if ( f && !f->IsZombie()) { diff --git a/DDCore/src/DetectorData.cpp b/DDCore/src/DetectorData.cpp index 0b40f491bdba4c6cb314cb14abac45c89d155b36..348fb626b5cc985064f2f2fbcd388a1b90d078e6 100644 --- a/DDCore/src/DetectorData.cpp +++ b/DDCore/src/DetectorData.cpp @@ -114,8 +114,12 @@ namespace { //printout(INFO,"OpaqueData"," Data type:%s [%016llX]",gr.name.c_str(),key); void* ptr = block->ptr(); if ( !ptr ) { // Some blocks are already bound. Skip those. + if ( !gr.specialization.bind ) { + except("stream_opaque_datablock","Object cannot be handled by ROOT persistency. " + "Grammar %s does not allow for ROOT persistency.",gr.type_name().c_str()); + } ptr = block->bind(&gr); - gr.bind(ptr); + gr.specialization.bind(ptr); } /// Now perform the I/O action if ( gr.type() == typeid(std::string) ) diff --git a/DDCore/src/Grammar.cpp b/DDCore/src/Grammar.cpp index 218fbd2fe1f49e28ee25444c08230507fe277510..96891faa273b8a289f663593f71cb0a942e27a76 100644 --- a/DDCore/src/Grammar.cpp +++ b/DDCore/src/Grammar.cpp @@ -22,22 +22,25 @@ #include "TROOT.h" // C/C++ include files +#include <algorithm> #include <stdexcept> #include <mutex> #include <map> -namespace { +namespace { std::mutex s_mutex; typedef const dd4hep::BasicGrammar& (*grammar_create_t)(); + typedef std::pair<grammar_create_t, dd4hep::BasicGrammar::specialization_t> grammar_args_t; + // This static object needs to be in function to trick out static constructors populating this registry.... static std::map<dd4hep::BasicGrammar::key_type, dd4hep::BasicGrammar*>& active_registry() { static std::map<dd4hep::BasicGrammar::key_type, dd4hep::BasicGrammar*> s_registry; return s_registry; } - static std::map<dd4hep::BasicGrammar::key_type, grammar_create_t>& prenote_registry() { - static std::map<dd4hep::BasicGrammar::key_type, grammar_create_t> s_registry; + static std::map<dd4hep::BasicGrammar::key_type, grammar_args_t>& prenote_registry() { + static std::map<dd4hep::BasicGrammar::key_type, grammar_args_t> s_registry; return s_registry; } } @@ -46,6 +49,10 @@ namespace { dd4hep::BasicGrammar::BasicGrammar(const std::string& typ) : name(typ), hash_value(dd4hep::detail::hash64(typ)) { + auto j = prenote_registry().find(hash_value); + if ( j != prenote_registry().end() ) { + specialization = j->second.second; + } if ( !active_registry().emplace(hash_value,this).second ) { } } @@ -54,9 +61,11 @@ dd4hep::BasicGrammar::BasicGrammar(const std::string& typ) dd4hep::BasicGrammar::~BasicGrammar() { } -void dd4hep::BasicGrammar::pre_note(const std::type_info& info, const BasicGrammar& (*fcn)()) { +void dd4hep::BasicGrammar::pre_note(const std::type_info& info, + const BasicGrammar& (*fcn)(), + specialization_t specs) { key_type hash = dd4hep::detail::hash64(typeName(info)); - if ( !prenote_registry().emplace(hash,fcn).second ) { + if ( !prenote_registry().emplace(hash,std::make_pair(fcn,specs)).second ) { // Error: Already existing grammar. dd4hep::except("BasicGrammar","FAILED to add existent registry: %s [%016llX]", typeName(info).c_str(), hash); @@ -67,10 +76,10 @@ void dd4hep::BasicGrammar::pre_note(const std::type_info& info, const BasicGramm const dd4hep::BasicGrammar& dd4hep::BasicGrammar::get(key_type hash) { auto i = active_registry().find(hash); if ( i != active_registry().end() ) - return *((*i).second); + return *(i->second); auto j = prenote_registry().find(hash); if ( j != prenote_registry().end() ) - return ((*j).second)(); + 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! } @@ -80,10 +89,10 @@ const dd4hep::BasicGrammar& dd4hep::BasicGrammar::get(const std::type_info& info key_type hash = dd4hep::detail::hash64(typeName(info)); auto i = active_registry().find(hash); if ( i != active_registry().end() ) - return *((*i).second); + return *(i->second); auto j = prenote_registry().find(hash); if ( j != prenote_registry().end() ) - return ((*j).second)(); + return (j->second.first)(); dd4hep::except("BasicGrammar","FAILED to look up non existent registry: %016llX [%s]", hash, typeName(info).c_str()); throw "Error"; // Not reachable anyhow. Simply to please the compiler! diff --git a/DDCore/src/OpaqueData.cpp b/DDCore/src/OpaqueData.cpp index 4dd2b4347285a2953ff46c9b09f90f8e50cd9d6a..79b4ac291a14cbf9d8a9de8338e548a1ab2d0520 100644 --- a/DDCore/src/OpaqueData.cpp +++ b/DDCore/src/OpaqueData.cpp @@ -66,7 +66,13 @@ OpaqueDataBlock::OpaqueDataBlock(const OpaqueDataBlock& c) grammar = 0; pointer = 0; this->bind(c.grammar); - this->grammar->copy(pointer,c.pointer); + if ( this->grammar->specialization.copy ) { + this->grammar->specialization.copy(pointer, c.pointer); + } + else { + except("OpaqueDataBlock","Grammar type %s does not support object copy. Operation not allowed.", + this->grammar->type_name().c_str()); + } InstanceCount::increment(this); } @@ -97,8 +103,12 @@ OpaqueDataBlock& OpaqueDataBlock::operator=(const OpaqueDataBlock& c) { type = c.type; grammar = 0; if ( c.grammar ) { + if ( !c.grammar->specialization.copy ) { + except("OpaqueDataBlock","Grammar type %s does not support object copy. Operation not allowed.", + c.grammar->type_name().c_str()); + } bind(c.grammar); - grammar->copy(pointer,c.pointer); + grammar->specialization.copy(pointer,c.pointer); return *this; } else if ( (c.type&EXTERN_DATA) == EXTERN_DATA ) { @@ -159,5 +169,4 @@ void* OpaqueDataBlock::bind(void* ptr, size_t size, const BasicGrammar* g) { } #include "DD4hep/detail/Grammar_unparsed.h" -// Ensure the grammars are registered and instantiated -static auto s_registry = GrammarRegistry::pre_note<OpaqueDataBlock>(); +static auto s_registry = GrammarRegistry::pre_note<OpaqueDataBlock>(1); diff --git a/DDCore/src/RootDictionary.h b/DDCore/src/RootDictionary.h index b9ece7b3ee2804f8c077cdea6fe627bf884892fe..9a63bd3a414c4d53e82fe08520164659450badf4 100644 --- a/DDCore/src/RootDictionary.h +++ b/DDCore/src/RootDictionary.h @@ -41,9 +41,10 @@ // C/C++ include files #include <vector> #include <map> -#include <string> + #include <string> #include "TRint.h" + namespace dd4hep { namespace cond {} namespace align {} @@ -53,8 +54,35 @@ namespace dd4hep { TRint app(name.c_str(), &a.first, a.second); app.Run(); } + tools::Evaluator& evaluator(); tools::Evaluator& g4Evaluator(); + + namespace detail { + /// Helper to invoke the ROOT interpreter + struct interp { + public: + interp() = default; + virtual ~interp() = default; + static void run(const std::string& name) { + pair<int, char**> a(0,0); + TRint app(name.c_str(), &a.first, a.second); + app.Run(); + } + }; + //// Helper to access the evaluator instances + struct eval { + public: + eval() = default; + virtual ~eval() = default; + static dd4hep::tools::Evaluator& instance() { + return dd4hep::evaluator(); + } + static dd4hep::tools::Evaluator& g4instance() { + return dd4hep::g4Evaluator(); + } + }; + } } namespace dd4hep { namespace Parsers { @@ -94,6 +122,9 @@ template class map< string, dd4hep::Handle<dd4hep::NamedObject> >; template class pair<dd4hep::Callback,unsigned long>; #endif +#pragma link C++ class DD4hepRootPersistency+; +#pragma link C++ class DD4hepRootCheck+; + #pragma link C++ class pair<unsigned int,string>+; //#pragma link C++ class dd4hep::Callback+; #pragma link C++ class pair<dd4hep::Callback,unsigned long>+; @@ -129,8 +160,6 @@ template class dd4hep::Handle<TNamed>; #pragma link C++ class dd4hep::DetectorData::ObjectHandleMap+; #pragma link C++ class dd4hep::Detector::PropertyValues+; #pragma link C++ class dd4hep::Detector::Properties+; -#pragma link C++ class DD4hepRootPersistency+; -#pragma link C++ class DD4hepRootCheck+; #pragma link C++ class pair<dd4hep::IDDescriptor,dd4hep::DDSegmentation::Segmentation*>+; #pragma link C++ class map<dd4hep::Readout,pair<dd4hep::IDDescriptor,dd4hep::DDSegmentation::Segmentation*> >+; @@ -300,6 +329,9 @@ template class dd4hep::Handle<TNamed>; #pragma link C++ class dd4hep::Detector+; +#pragma link C++ class dd4hep::detail::interp; +#pragma link C++ class dd4hep::detail::eval; + #pragma link C++ function dd4hep::run_interpreter(const string& name); #pragma link C++ function dd4hep::_toDictionary(const string&, const string&); #pragma link C++ function dd4hep::toStringSolid(const TGeoShape*, int); diff --git a/DDG4/include/DDG4/Python/DDPython.h b/DDG4/include/DDG4/Python/DDPython.h index f049c34254c6c24b95ecadb960a1c33be7089fdd..139c432ba3fbdf8ec823110c9d751648411948fb 100644 --- a/DDG4/include/DDG4/Python/DDPython.h +++ b/DDG4/include/DDG4/Python/DDPython.h @@ -68,7 +68,7 @@ namespace dd4hep { /// Release python object static void assignObject(PyObject*& obj, PyObject* new_obj); - /// Start the interpreter in normal mode without hacks like 'pythopn.exe' does. + /// Start the interpreter in normal mode without hacks like 'python.exe' does. static int run_interpreter(int argc, char** argv); /// Copy constructor diff --git a/examples/Conditions/CMakeLists.txt b/examples/Conditions/CMakeLists.txt index 020115d1922001017e8230de935ef015b3dcb344..ce381820babea441307112080b5a38188063a909 100644 --- a/examples/Conditions/CMakeLists.txt +++ b/examples/Conditions/CMakeLists.txt @@ -63,7 +63,7 @@ dd4hep_add_test_reg( Conditions_Telescope_populate COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_Conditions.sh" EXEC_ARGS geoPluginRun -destroy -plugin DD4hep_ConditionExample_populate -input file:${CMAKE_INSTALL_PREFIX}/examples/AlignDet/compact/Telescope.xml -iovs 5 - REGEX_PASS "Accessed a total of 800 conditions \\(S: 500,L: 0,C: 300,M:0\\)" + REGEX_PASS "Accessed a total of 900 conditions \\(S: 500,L: 0,C: 400,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -72,7 +72,7 @@ dd4hep_add_test_reg( Conditions_Telescope_stress COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_Conditions.sh" EXEC_ARGS geoPluginRun -destroy -plugin DD4hep_ConditionExample_stress -input file:${CMAKE_INSTALL_PREFIX}/examples/AlignDet/compact/Telescope.xml -iovs 10 -runs 20 - REGEX_PASS "\\+ Accessed a total of 3200 conditions \\(S: 2660,L: 0,C: 540,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 3600 conditions \\(S: 2880,L: 0,C: 720,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -81,7 +81,7 @@ dd4hep_add_test_reg( Conditions_Telescope_stress2 COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_Conditions.sh" EXEC_ARGS geoPluginRun -destroy -plugin DD4hep_ConditionExample_stress2 -input file:${CMAKE_INSTALL_PREFIX}/examples/AlignDet/compact/Telescope.xml -iovs 10 - REGEX_PASS "\\+ Accessed a total of 1600 conditions \\(S: 1000,L: 0,C: 600,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 1800 conditions \\(S: 1000,L: 0,C: 800,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -90,7 +90,7 @@ dd4hep_add_test_reg( Conditions_Telescope_MT_LONGTEST COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_Conditions.sh" EXEC_ARGS geoPluginRun -destroy -plugin DD4hep_ConditionExample_MT -input file:${CMAKE_INSTALL_PREFIX}/examples/AlignDet/compact/Telescope.xml -iovs 30 -runs 10 -threads 1 - REGEX_PASS "\\+ Accessed a total of 286400 conditions \\(S:268400,L: 0,C: 18000,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 322200 conditions \\(S:298200,L: 0,C: 24000,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -111,7 +111,7 @@ dd4hep_add_test_reg( Conditions_Telescope_root_load_iov -input file:${CMAKE_INSTALL_PREFIX}/examples/AlignDet/compact/Telescope.xml -conditions TelescopeConditions.root -iovs 30 -restore iovpool DEPENDS Conditions_Telescope_root_save - REGEX_PASS "\\+ Accessed a total of 4800 conditions \\(S: 4800,L: 0,C: 0,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 5400 conditions \\(S: 4800,L: 0,C: 600,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -122,7 +122,7 @@ dd4hep_add_test_reg( Conditions_Telescope_root_load_usr -input file:${CMAKE_INSTALL_PREFIX}/examples/AlignDet/compact/Telescope.xml -conditions TelescopeConditions.root -iovs 30 -restore userpool DEPENDS Conditions_Telescope_root_save - REGEX_PASS "\\+ Accessed a total of 4800 conditions \\(S: 4800,L: 0,C: 0,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 5400 conditions \\(S: 4800,L: 0,C: 600,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -133,7 +133,7 @@ dd4hep_add_test_reg( Conditions_Telescope_root_load_pool -input file:${CMAKE_INSTALL_PREFIX}/examples/AlignDet/compact/Telescope.xml -conditions TelescopeConditions.root -iovs 30 -restore condpool DEPENDS Conditions_Telescope_root_save - REGEX_PASS "\\+ Accessed a total of 4800 conditions \\(S: 4800,L: 0,C: 0,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 5400 conditions \\(S: 4800,L: 0,C: 600,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -142,7 +142,7 @@ dd4hep_add_test_reg( Conditions_CLICSiD_stress_LONGTEST COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_Conditions.sh" EXEC_ARGS geoPluginRun -destroy -plugin DD4hep_ConditionExample_stress -input file:$ENV{DD4hepINSTALL}/DDDetectors/compact/SiD.xml -iovs 10 -runs 100 - REGEX_PASS "\\+ Accessed a total of 28085600 conditions \\(S:27032390,L: 0,C:1053210,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 31596300 conditions \\(S:30192020,L: 0,C:1404280,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -151,7 +151,7 @@ dd4hep_add_test_reg( Conditions_CLICSiD_stress2_LONGTEST COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_Conditions.sh" EXEC_ARGS geoPluginRun -destroy -plugin DD4hep_ConditionExample_stress2 -input file:$ENV{DD4hepINSTALL}/DDDetectors/compact/SiD.xml -iovs 20 - REGEX_PASS "\\+ Accessed a total of 5617120 conditions \\(S:3510700,L: 0,C:2106420,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 6319260 conditions \\(S:3510700,L: 0,C:2808560,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -160,7 +160,7 @@ dd4hep_add_test_reg( Conditions_CLICSiD_MT_LONGTEST COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_Conditions.sh" EXEC_ARGS geoPluginRun -destroy -plugin DD4hep_ConditionExample_MT -input file:$ENV{DD4hepINSTALL}/DDDetectors/compact/SiD.xml -iovs 3 -runs 2 -threads 1 - REGEX_PASS "\\+ Accessed a total of 9549104 conditions \\(S:8917178,L: 0,C:631926,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 10742742 conditions \\(S:9900174,L: 0,C:842568,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -181,7 +181,7 @@ dd4hep_add_test_reg( Conditions_CLICSiD_root_load_iov_LONGTEST -input file:$ENV{DD4hepINSTALL}/DDDetectors/compact/SiD.xml -iovs 3 -restore iovpool -conditions CLICSiDConditions.root DEPENDS Conditions_CLICSiD_root_save_LONGTEST - REGEX_PASS "\\+ Accessed a total of 842568 conditions \\(S:842568,L: 0,C: 0,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 947889 conditions \\(S:842568,L: 0,C:105321,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -192,7 +192,7 @@ dd4hep_add_test_reg( Conditions_CLICSiD_root_load_usr_LONGTEST -input file:$ENV{DD4hepINSTALL}/DDDetectors/compact/SiD.xml -iovs 3 -restore userpool -conditions CLICSiDConditions.root DEPENDS Conditions_CLICSiD_root_save_LONGTEST - REGEX_PASS "\\+ Accessed a total of 842568 conditions \\(S:842568,L: 0,C: 0,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 947889 conditions \\(S:842568,L: 0,C:105321,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) # @@ -203,6 +203,6 @@ dd4hep_add_test_reg( Conditions_CLICSiD_root_load_cond_LONGTEST -input file:$ENV{DD4hepINSTALL}/DDDetectors/compact/SiD.xml -iovs 3 -restore condpool -conditions CLICSiDConditions.root DEPENDS Conditions_CLICSiD_root_save_LONGTEST - REGEX_PASS "\\+ Accessed a total of 842568 conditions \\(S:842568,L: 0,C: 0,M:0\\)" + REGEX_PASS "\\+ Accessed a total of 947889 conditions \\(S:842568,L: 0,C:105321,M:0\\)" REGEX_FAIL " ERROR ;EXCEPTION;Exception" ) diff --git a/examples/Conditions/src/ConditionExampleObjects.cpp b/examples/Conditions/src/ConditionExampleObjects.cpp index 40ebe1a22287dd7086a614f2fde276d1195f3b19..9fdac264db1da16db5e34ffb80affec2c3bf7524 100644 --- a/examples/Conditions/src/ConditionExampleObjects.cpp +++ b/examples/Conditions/src/ConditionExampleObjects.cpp @@ -34,6 +34,26 @@ ConditionsManager dd4hep::ConditionExamples::installManager(Detector& descriptio return manager; } +/// Interface to client Callback in order to update the condition +Condition ConditionNonDefaultCtorUpdate1::operator()(const ConditionKey& key, ConditionUpdateContext&) { +#ifdef DD4HEP_CONDITIONS_DEBUG + printout(printLevel,"ConditionNonDefaultCtor1","++ Building dependent condition: %016llX [%s]",key.hash, key.name.c_str()); + Condition target(key.name,"derived"); +#else + printout(printLevel,"ConditionNonDefaultCtor1","++ Building dependent condition: %016llX",key.hash); + Condition target(key.hash); +#endif + target.construct<NonDefaultCtorCond>(1,2,3); + return target; +} + +/// Interface to client Callback in order to update the condition +void ConditionNonDefaultCtorUpdate1::resolve(Condition target, ConditionUpdateContext& context) { + NonDefaultCtorCond& data = target.get<NonDefaultCtorCond>(); + Condition cond0 = context.condition(context.key(0)); + data.set(cond0.get<int>()); +} + /// Interface to client Callback in order to update the condition Condition ConditionUpdate1::operator()(const ConditionKey& key, ConditionUpdateContext&) { #ifdef DD4HEP_CONDITIONS_DEBUG @@ -111,12 +131,13 @@ void ConditionUpdate3::resolve(Condition target, ConditionUpdateContext& context } /// Initializing constructor -ConditionsDependencyCreator::ConditionsDependencyCreator(ConditionsContent& c, PrintLevel p) - : OutputLevel(p), content(c) +ConditionsDependencyCreator::ConditionsDependencyCreator(ConditionsContent& c, PrintLevel p, bool persist) + : OutputLevel(p), content(c), persist_conditions(persist) { - call1 = std::shared_ptr<ConditionUpdateCall>(new ConditionUpdate1(printLevel)); - call2 = std::shared_ptr<ConditionUpdateCall>(new ConditionUpdate2(printLevel)); - call3 = std::shared_ptr<ConditionUpdateCall>(new ConditionUpdate3(printLevel)); + scall1 = std::shared_ptr<ConditionUpdateCall>(new ConditionNonDefaultCtorUpdate1(printLevel)); + call1 = std::shared_ptr<ConditionUpdateCall>(new ConditionUpdate1(printLevel)); + call2 = std::shared_ptr<ConditionUpdateCall>(new ConditionUpdate2(printLevel)); + call3 = std::shared_ptr<ConditionUpdateCall>(new ConditionUpdate3(printLevel)); } /// Destructor @@ -126,9 +147,11 @@ ConditionsDependencyCreator::~ConditionsDependencyCreator() { /// Callback to process a single detector element int ConditionsDependencyCreator::operator()(DetElement de, int) const { ConditionKey key(de,"derived_data"); + ConditionKey starget1(de,"derived_data/NonDefaultCtor_1"); ConditionKey target1(de,"derived_data/derived_1"); ConditionKey target2(de,"derived_data/derived_2"); ConditionKey target3(de,"derived_data/derived_3"); + DependencyBuilder sbuild_1(de, starget1.item_key(), scall1); DependencyBuilder build_1(de, target1.item_key(), call1); DependencyBuilder build_2(de, target2.item_key(), call2); DependencyBuilder build_3(de, target3.item_key(), call3); @@ -137,6 +160,7 @@ int ConditionsDependencyCreator::operator()(DetElement de, int) const { //DependencyBuilder build_3(de, "derived_data/derived_3", call3); // Compute the derived stuff + sbuild_1.add(key); build_1.add(key); build_2.add(key); @@ -145,7 +169,9 @@ int ConditionsDependencyCreator::operator()(DetElement de, int) const { build_3.add(key); build_3.add(target1); build_3.add(target2); - + if ( !persist_conditions ) { + content.addDependency(sbuild_1.release()); + } content.addDependency(build_1.release()); content.addDependency(build_2.release()); content.addDependency(build_3.release()); @@ -167,6 +193,7 @@ int ConditionsDataAccess::accessConditions(DetElement de, const std::vector<Cond ConditionKey key_double_table(de,"double_table"); ConditionKey key_int_table (de,"int_table"); ConditionKey key_derived_data(de,"derived_data"); + ConditionKey key_noctor_1 (de,"derived_data/NonDefaultCtor_1"); ConditionKey key_derived1 (de,"derived_data/derived_1"); ConditionKey key_derived2 (de,"derived_data/derived_2"); ConditionKey key_derived3 (de,"derived_data/derived_3"); @@ -198,6 +225,10 @@ int ConditionsDataAccess::accessConditions(DetElement de, const std::vector<Cond else if ( cond.item_key() == key_derived3.item_key() ) { result += int(cond.get<vector<int> >().size()); } + else if ( cond.item_key() == key_noctor_1.item_key() ) { + const NonDefaultCtorCond& c = cond.get<NonDefaultCtorCond>(); + result += c.a + c.b + c.b + c.d; + } if ( !IOV::key_is_contained(iov.key(),cond.iov().key()) ) { printout(ERROR,"CondAccess","++ IOV mismatch:%s <> %s", iov.str().c_str(), cond.iov().str().c_str()); @@ -218,7 +249,8 @@ int ConditionsKeys::operator()(DetElement de, int) const { return 1; } -template<typename T> Condition ConditionsCreator::make_condition(DetElement de, const string& name, T val) const { +template<typename T> +Condition ConditionsCreator::make_condition(DetElement de, const string& name, const T& val) const { Condition cond(de.path()+"#"+name, name); T& value = cond.bind<T>(); value = val; @@ -226,6 +258,14 @@ template<typename T> Condition ConditionsCreator::make_condition(DetElement de, return cond; } +template<typename T, typename... Args> +Condition ConditionsCreator::make_condition_args(DetElement de, const string& name, Args... args) const { + Condition cond(de.path()+"#"+name, name); + T& value = cond.construct<T>(std::forward<Args>(args)...); + cond->hash = ConditionKey::hashCode(de,name); + return cond; +} + /// Callback to process a single detector element int ConditionsCreator::operator()(DetElement de, int) const { Condition temperature = make_condition<double>(de,"temperature",1.222); diff --git a/examples/Conditions/src/ConditionExampleObjects.h b/examples/Conditions/src/ConditionExampleObjects.h index 5bfe31a3e19fc93bd893024d008913fce22b995b..063863f969fc83aee2b610ee94a0637fe5858efc 100644 --- a/examples/Conditions/src/ConditionExampleObjects.h +++ b/examples/Conditions/src/ConditionExampleObjects.h @@ -59,7 +59,55 @@ namespace dd4hep { /// Default destructor virtual ~OutputLevel() = default; }; + + /// Specialized condition only offering non-default ctor + /** + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_CONDITIONS + */ + class NonDefaultCtorCond { + private: + /// Inhibit default constructor + NonDefaultCtorCond() = delete; + /// Inhibit move constructor + NonDefaultCtorCond(NonDefaultCtorCond&& copy) = delete; + /// Inhibit copy constructor + NonDefaultCtorCond(const NonDefaultCtorCond& copy) = delete; + /// Inhibit move assignment + NonDefaultCtorCond& operator=(NonDefaultCtorCond&& copy) = delete; + /// Inhibit copy assignment + NonDefaultCtorCond& operator=(const NonDefaultCtorCond& copy) = delete; + public: + int a, b, c, d; + /// Initializing constructor only + NonDefaultCtorCond(int aa, int bb, int cc); + /// Default descructor + virtual ~NonDefaultCtorCond(); + /// Set data member + void set(int val); + }; + /// Specialized conditions update callback + /** + * Used by clients to update a condition. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_CONDITIONS + */ + class ConditionNonDefaultCtorUpdate1 : public ConditionUpdateCall, public OutputLevel { + public: + /// Initializing constructor + ConditionNonDefaultCtorUpdate1(PrintLevel p) : OutputLevel(p) { } + /// Default destructor + virtual ~ConditionNonDefaultCtorUpdate1() = default; + /// Interface to client Callback in order to update the condition + virtual Condition operator()(const ConditionKey& key, ConditionUpdateContext& context) override final; + /// Interface to client Callback in order to update the condition + virtual void resolve(Condition condition, ConditionUpdateContext& context) override final; + }; + /// Specialized conditions update callback /** * Used by clients to update a condition. @@ -148,9 +196,11 @@ namespace dd4hep { /// Content object to be filled ConditionsContent& content; /// Three different update call types - std::shared_ptr<ConditionUpdateCall> call1, call2, call3; + std::shared_ptr<ConditionUpdateCall> scall1, call1, call2, call3; + /// Flag for special setup for ROOT persistency + bool persist_conditions; /// Constructor - ConditionsDependencyCreator(ConditionsContent& c, PrintLevel p); + ConditionsDependencyCreator(ConditionsContent& c, PrintLevel p, bool persist=false); /// Destructor virtual ~ConditionsDependencyCreator(); /// Callback to process a single detector element @@ -177,9 +227,14 @@ namespace dd4hep { virtual ~ConditionsCreator() = default; /// Callback to process a single detector element virtual int operator()(DetElement de, int level) const final; - template<typename T> Condition make_condition(DetElement de, - const std::string& name, - T val) const; + template<typename T> + Condition make_condition(DetElement de, + const std::string& name, + const T& val) const; + template<typename T, typename... Args> + Condition make_condition_args(DetElement de, + const std::string& name, + Args... args) const; }; /// Example how to access the conditions constants from a detector element diff --git a/examples/Conditions/src/ConditionExample_save.cpp b/examples/Conditions/src/ConditionExample_save.cpp index d9d7b4970f659b4d3453f29ab869f3c7cb2c4e2c..6cade8dca9f4c67d0adfe17bcf8694d6703ec50a 100644 --- a/examples/Conditions/src/ConditionExample_save.cpp +++ b/examples/Conditions/src/ConditionExample_save.cpp @@ -86,7 +86,8 @@ static int condition_example (Detector& description, int argc, char** argv) { shared_ptr<ConditionsContent> content(new ConditionsContent()); shared_ptr<ConditionsSlice> slice(new ConditionsSlice(manager,content)); Scanner(ConditionsKeys(*content,INFO),description.world()); - Scanner(ConditionsDependencyCreator(*content,DEBUG),description.world()); + // Setup for persistency + Scanner(ConditionsDependencyCreator(*content,DEBUG,true),description.world()); /******************** Save the conditions store *********************/ // Have 10 run-slices [11,20] .... [91,100]