Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/JANA/JMultifactory.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 
0002 // Copyright 2023, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 #pragma once
0006 
0007 #include "JANA/Utils/JTypeInfo.h"
0008 #include <JANA/JFactoryT.h>
0009 #include <JANA/JFactorySet.h>
0010 #include <JANA/Components/JComponent.h>
0011 #include <JANA/Components/JHasRunCallbacks.h>
0012 #include <JANA/JVersion.h>
0013 
0014 #if JANA2_HAVE_PODIO
0015 #include "JANA/Podio/JFactoryPodioT.h"
0016 #endif
0017 
0018 class JMultifactory;
0019 
0020 template <typename T>
0021 class JMultifactoryHelper : public JFactoryT<T>{
0022 
0023     JMultifactory* mMultiFactory;
0024 
0025 public:
0026     JMultifactoryHelper(JMultifactory* parent) : mMultiFactory(parent) {}
0027     virtual ~JMultifactoryHelper() = default;
0028     // This does NOT own mMultiFactory; the enclosing JFactorySet does
0029 
0030     void Process(const std::shared_ptr<const JEvent>&) override;
0031     // We really want to override Create, not Process!!!
0032     // It might make more sense to (1) put Create() back on JFactory, (2) make Create() virtual, (3) override Create()
0033     // Alternatively, we could move all the JMultiFactoryHelper functionality into JFactoryT directly
0034 
0035     JMultifactory* GetMultifactory() { return mMultiFactory; }
0036 
0037     // Helpers do not produce any summary information
0038     void Summarize(JComponentSummary&) const override { }
0039 };
0040 
0041 
0042 #if JANA2_HAVE_PODIO
0043 // TODO: This redundancy goes away if we merge JFactoryPodioT with JFactoryT
0044 template <typename T>
0045 class JMultifactoryHelperPodio : public JFactoryPodioT<T>{
0046 
0047     JMultifactory* mMultiFactory;
0048 
0049 public:
0050     JMultifactoryHelperPodio(JMultifactory* parent) : mMultiFactory(parent) {}
0051 
0052     virtual ~JMultifactoryHelperPodio() = default;
0053     // This does NOT own mMultiFactory; the enclosing JFactorySet does
0054 
0055     void Process(const std::shared_ptr<const JEvent>&) override;
0056     // We really want to override Create, not Process!!!
0057     // It might make more sense to (1) put Create() back on JFactory, (2) make Create() virtual, (3) override Create()
0058     // Alternatively, we could move all of the JMultiFactoryHelper functionality into JFactoryT directly
0059 
0060     JMultifactory* GetMultifactory() { return mMultiFactory; }
0061 
0062     // Helpers do not produce any summary information
0063     void Summarize(JComponentSummary&) const override { }
0064 };
0065 #endif // JANA2_HAVE_PODIO
0066 
0067 
0068 class JMultifactory : public jana::components::JComponent,
0069                       public jana::components::JHasRunCallbacks {
0070 
0071     JFactorySet mHelpers; // This has ownership UNTIL JFactorySet::Add() takes it over
0072 
0073     // Remember where we are in the stream so that the correct sequence of callbacks get called.
0074     // However, don't worry about a Status variable. Every time Execute() gets called, so does Process().
0075     // The JMultifactoryHelpers will control calls to Execute().
0076 
0077 #if JANA2_HAVE_PODIO
0078     bool mNeedPodio = false;      // Whether we need to retrieve the podio::Frame
0079     podio::Frame* mPodioFrame = nullptr;  // To provide the podio::Frame to SetPodioData, SetCollection
0080 #endif
0081 
0082 public:
0083     JMultifactory() = default;
0084     virtual ~JMultifactory() = default;
0085 
0086     // IMPLEMENTED BY USERS
0087 
0088     virtual void Init() {}
0089     void BeginRun(const std::shared_ptr<const JEvent>&) override {}
0090     virtual void Process(const std::shared_ptr<const JEvent>&) {}
0091     void EndRun() override {}
0092     virtual void Finish() {}
0093     // I'm tempted to factor out something like JEventCallback from JFactory, JMultifactory, and JEventProcessor.
0094 
0095 
0096     // CALLED BY USERS
0097 
0098     template <typename T>
0099     void DeclareOutput(std::string tag, bool owns_data=true);
0100 
0101     template <typename T>
0102     void SetData(std::string tag, std::vector<T*> data);
0103 
0104 #if JANA2_HAVE_PODIO
0105 
0106     template <typename T>
0107     void DeclarePodioOutput(std::string tag, bool owns_data=true);
0108 
0109     template <typename T>
0110     void SetCollection(std::string tag, typename JFactoryPodioT<T>::CollectionT&& collection);
0111 
0112     template <typename T>
0113     void SetCollection(std::string tag, std::unique_ptr<typename JFactoryPodioT<T>::CollectionT> collection);
0114 
0115 #endif
0116 
0117     /// CALLED BY JANA
0118     
0119     void DoInit();
0120 
0121     void Execute(const std::shared_ptr<const JEvent>&);
0122     // Should this be execute or create? Who is tracking that this is called at most once per event?
0123     // Do we need something like JFactory::Status? Also, how do we ensure that CreationStatus is correct as well?
0124 
0125     void Release();
0126     // Release makes sure Finish() is called exactly once
0127 
0128     JFactorySet* GetHelpers();
0129     // This exposes the mHelpers JFactorySet, which contains a JFactoryT<T> for each declared output of the multifactory.
0130     // This is meant to be called from JFactorySet, which will take ownership of the helpers while leaving the pointers
0131     // in place. This method is only supposed to be called by JFactorySet::Add(JMultifactory).
0132 
0133     // These are set by JFactoryGeneratorT (just like JFactories) and get propagated to each of the JMultifactoryHelpers
0134     void SetTag(std::string tag) { SetPrefix(tag); }
0135 
0136     void SetFactoryName(std::string factoryName) { 
0137         SetTypeName(factoryName);
0138     }
0139     
0140     void Summarize(JComponentSummary& summary) const override;
0141 };
0142 
0143 
0144 
0145 template <typename T>
0146 void JMultifactory::DeclareOutput(std::string tag, bool owns_data) {
0147     JFactory* helper = new JMultifactoryHelper<T>(this);
0148     if (!owns_data) helper->SetFactoryFlag(JFactory::JFactory_Flags_t::NOT_OBJECT_OWNER);
0149     helper->SetPluginName(m_plugin_name);
0150     helper->SetFactoryName(GetTypeName()+"::Helper<" + JTypeInfo::demangle<T>() + ">");
0151     helper->SetTag(std::move(tag));
0152     helper->SetLevel(GetLevel());
0153     mHelpers.SetLevel(GetLevel());
0154     mHelpers.Add(helper);
0155 }
0156 
0157 template <typename T>
0158 void JMultifactory::SetData(std::string tag, std::vector<T*> data) {
0159     JFactoryT<T>* helper = mHelpers.GetFactory<T>(tag);
0160     if (helper == nullptr) {
0161         auto ex = JException("JMultifactory: Attempting to SetData() without corresponding DeclareOutput()");
0162         ex.function_name = "JMultifactory::SetData";
0163         ex.type_name = m_type_name;
0164         ex.instance_name = m_prefix;
0165         ex.plugin_name = m_plugin_name;
0166         throw ex;
0167     }
0168 #if JANA2_HAVE_PODIO
0169     // This may or may not be a Podio factory. We find out if it is, and if so, set the frame before calling Set().
0170     auto* typed = dynamic_cast<JFactoryPodio*>(helper);
0171     if (typed != nullptr) {
0172         typed->SetFrame(mPodioFrame); // Needs to be called before helper->Set(), otherwise Set() excepts
0173     }
0174 #endif
0175     helper->Set(data);
0176 }
0177 
0178 
0179 #if JANA2_HAVE_PODIO
0180 
0181 template <typename T>
0182 void JMultifactory::DeclarePodioOutput(std::string tag, bool owns_data) {
0183     // TODO: Decouple tag name from collection name
0184     auto* helper = new JMultifactoryHelperPodio<T>(this);
0185     if (!owns_data) helper->SetSubsetCollection(true);
0186 
0187     helper->SetTag(std::move(tag));
0188     helper->SetPluginName(m_plugin_name);
0189     helper->SetFactoryName(GetTypeName() + "::Helper<" + JTypeInfo::demangle<T>() + ">");
0190     helper->SetLevel(GetLevel());
0191     mHelpers.SetLevel(GetLevel());
0192     mHelpers.Add(helper);
0193     mNeedPodio = true;
0194 }
0195 
0196 template <typename T>
0197 void JMultifactory::SetCollection(std::string tag, typename JFactoryPodioT<T>::CollectionT&& collection) {
0198     JFactoryT<T>* helper = mHelpers.GetFactory<T>(tag);
0199     if (helper == nullptr) {
0200         auto ex = JException("JMultifactory: Attempting to SetData() without corresponding DeclareOutput()");
0201         ex.function_name = "JMultifactory::SetCollection";
0202         ex.type_name = m_type_name;
0203         ex.instance_name = m_prefix;
0204         ex.plugin_name = m_plugin_name;
0205         throw ex;
0206     }
0207     auto* typed = dynamic_cast<JFactoryPodioT<T>*>(helper);
0208     if (typed == nullptr) {
0209         auto ex = JException("JMultifactory: Helper needs to be a JFactoryPodioT (this shouldn't be reachable)");
0210         ex.function_name = "JMultifactory::SetCollection";
0211         ex.type_name = m_type_name;
0212         ex.instance_name = m_prefix;
0213         ex.plugin_name = m_plugin_name;
0214         throw ex;
0215     }
0216 
0217     typed->SetFrame(mPodioFrame);
0218     typed->SetCollection(std::move(collection));
0219 }
0220 
0221 template <typename T>
0222 void JMultifactory::SetCollection(std::string tag, std::unique_ptr<typename JFactoryPodioT<T>::CollectionT> collection) {
0223     JFactoryT<T>* helper = mHelpers.GetFactory<T>(tag);
0224     if (helper == nullptr) {
0225         auto ex = JException("JMultifactory: Attempting to SetData() without corresponding DeclareOutput()");
0226         ex.function_name = "JMultifactory::SetCollection";
0227         ex.type_name = m_type_name;
0228         ex.instance_name = m_prefix;
0229         ex.plugin_name = m_plugin_name;
0230         throw ex;
0231     }
0232     auto* typed = dynamic_cast<JFactoryPodioT<T>*>(helper);
0233     if (typed == nullptr) {
0234         auto ex = JException("JMultifactory: Helper needs to be a JFactoryPodioT (this shouldn't be reachable)");
0235         ex.function_name = "JMultifactory::SetCollection";
0236         ex.type_name = m_type_name;
0237         ex.instance_name = m_prefix;
0238         ex.plugin_name = m_plugin_name;
0239         throw ex;
0240     }
0241 
0242     typed->SetFrame(mPodioFrame);
0243     typed->SetCollection(std::move(collection));
0244 }
0245 
0246 #endif // JANA2_HAVE_PODIO
0247 
0248 
0249 template <typename T>
0250 void JMultifactoryHelper<T>::Process(const std::shared_ptr<const JEvent> &event) {
0251     mMultiFactory->Execute(event);
0252 }
0253 
0254 #if JANA2_HAVE_PODIO
0255 template <typename T>
0256 void JMultifactoryHelperPodio<T>::Process(const std::shared_ptr<const JEvent> &event) {
0257     mMultiFactory->Execute(event);
0258 }
0259 #endif // JANA2_HAVE_PODIO
0260 
0261