Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:41:07

0001 
0002 // Copyright 2020, 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/JException.h>
0008 #include <JANA/Utils/JAny.h>
0009 #include <JANA/Utils/JEventLevel.h>
0010 #include <JANA/Utils/JCallGraphRecorder.h>
0011 #include <JANA/Components/JComponent.h>
0012 #include <JANA/Components/JHasInputs.h>
0013 #include <JANA/Components/JHasOutputs.h>
0014 #include <JANA/Components/JHasRunCallbacks.h>
0015 #include <JANA/JVersion.h>
0016 #if JANA2_HAVE_PODIO
0017 #include <JANA/Components/JPodioOutput.h>
0018 #endif
0019 #include <JANA/Components/JLightweightOutput.h>
0020 
0021 #include <string>
0022 #include <typeindex>
0023 #include <memory>
0024 #include <vector>
0025 #include <unordered_map>
0026 #include <functional>
0027 
0028 
0029 class JEvent;
0030 class JObject;
0031 class JApplication;
0032 
0033 class JFactory : public jana::components::JComponent,
0034                  public jana::components::JHasRunCallbacks,
0035                  public jana::components::JHasInputs,
0036                  public jana::components::JHasOutputs {
0037 public:
0038 
0039     enum class Status {Uninitialized, Unprocessed, Processed, Inserted, Excepted, Finished};
0040     enum class CreationStatus { NotCreatedYet, Created, Inserted, InsertedViaGetObjects, NeverCreated };
0041 
0042     enum JFactory_Flags_t {
0043         JFACTORY_NULL = 0x00,    // Not used anywhere
0044         PERSISTENT = 0x01,       // Used heavily. Possibly better served by JServices, hierarchical events, or event groups. 
0045         WRITE_TO_OUTPUT = 0x02,  // Set in halld_recon but not read except by JANA1 janaroot and janacontrol plugins
0046         NOT_OBJECT_OWNER = 0x04, // Used heavily. Small conflict with PODIO subset collections, which do the same thing at a different level
0047         REGENERATE = 0x08        // Replaces JANA1 JFactory_base::use_factory and JFactory::GetCheckSourceFirst()
0048     };
0049 
0050     JFactory() {
0051         // Use CallbackStyle::ExpertMode any time we are NOT using JFactoryT
0052         // This retains backwards compatibility but also moves new code forward by default
0053         SetCallbackStyle(CallbackStyle::ExpertMode);
0054     }
0055     virtual ~JFactory() = default;
0056 
0057     void SetTag(std::string tag) {
0058         GetFirstDatabundle()->SetShortName(tag);
0059     }
0060 
0061     std::string GetTag() const { 
0062         auto db = GetFirstDatabundle();
0063         if (db->HasShortName()) {
0064             return db->GetShortName();
0065         }
0066         return db->GetUniqueName();
0067     }
0068 
0069     std::string GetObjectName() const { return mObjectName; }
0070 
0071     void SetObjectName(std::string object_name) { mObjectName = object_name; }
0072 
0073     std::string GetFactoryName() const { return m_type_name; }
0074     Status GetStatus() const { return mStatus; }
0075     CreationStatus GetCreationStatus() const { return mCreationStatus; }
0076     JCallGraphRecorder::JDataOrigin GetInsertOrigin() const { return m_insert_origin; } ///< If objects were placed here by JEvent::Insert() this records whether that call was made from a source or factory.
0077 
0078     uint32_t GetPreviousRunNumber(void) const { return mPreviousRunNumber; }
0079 
0080     void SetFactoryName(std::string factoryName) { SetTypeName(factoryName); }
0081     void SetStatus(Status status){ mStatus = status; }
0082     void SetCreationStatus(CreationStatus status){ mCreationStatus = status; }
0083     void SetInsertOrigin(JCallGraphRecorder::JDataOrigin origin) { m_insert_origin = origin; } ///< Called automatically by JEvent::Insert() to records whether that call was made by a source or factory.
0084 
0085     void SetPreviousRunNumber(uint32_t aRunNumber) { mPreviousRunNumber = aRunNumber; }
0086 
0087     virtual void SetFactoryFlag(JFactory_Flags_t f) {
0088         switch (f) {
0089             case JFactory::PERSISTENT: SetPersistentFlag(true); break;
0090             case JFactory::REGENERATE: SetRegenerateFlag(false); break;
0091             case JFactory::WRITE_TO_OUTPUT: SetWriteToOutputFlag(false); break;
0092             default: throw JException("Unsupported factory flag");
0093         }
0094     };
0095 
0096     void SetPersistentFlag(bool persistent) { mPersistent = persistent; }
0097     void SetRegenerateFlag(bool regenerate) { mRegenerate = regenerate; }
0098     void SetWriteToOutputFlag(bool write_to_output) { mWriteToOutput = write_to_output; }
0099     bool GetWriteToOutputFlag() { return mWriteToOutput; }
0100 
0101     /// Get data source value depending on how objects came to be here. (Used mainly by JEvent::Get() )
0102     inline JCallGraphRecorder::JDataSource GetDataSource() const {
0103         JCallGraphRecorder::JDataSource datasource = JCallGraphRecorder::DATA_FROM_FACTORY;
0104          if( mCreationStatus == JFactory::CreationStatus::Inserted ){
0105             if( m_insert_origin == JCallGraphRecorder::ORIGIN_FROM_SOURCE ){
0106                 datasource = JCallGraphRecorder::DATA_FROM_SOURCE;
0107             }else{
0108                 datasource = JCallGraphRecorder::DATA_FROM_CACHE; // Really came from factory, but if Inserted, it was a secondary data type.
0109             }
0110         }
0111         return datasource;
0112     }
0113 
0114     std::type_index GetObjectType() const {
0115         return GetFirstDatabundle()->GetTypeIndex();
0116     }
0117 
0118     std::size_t GetNumObjects() const {
0119         return GetFirstDatabundle()->GetSize();
0120     }
0121 
0122     void ClearData() {
0123         if (this->mStatus == JFactory::Status::Uninitialized) {
0124             return;
0125         }
0126 
0127         if (mPersistent) {
0128             // Persistence is a property of both the factory AND the databundle
0129             // - "Don't re-run this factory on the next event"
0130             // - "Don't clear this databundle every time the JEvent gets recycled"
0131             // Factory is persistent <=> All databundles are persistent
0132             // We ARE allowing databundles to be persistent even if they don't have a JFactory
0133             // We don't have a way to enforce this generally yet
0134             return;
0135         }
0136 
0137         this->mStatus = JFactory::Status::Unprocessed;
0138         this->mCreationStatus = JFactory::CreationStatus::NotCreatedYet;
0139 
0140         for (auto* output: GetOutputs()) {
0141             output->ClearData();
0142         }
0143         for (auto* variadic_output : GetVariadicOutputs()) {
0144             variadic_output->ClearData();
0145         }
0146     }
0147 
0148 
0149     // Overloaded by user Factories
0150     virtual void Init() {}
0151     virtual void Process(const std::shared_ptr<const JEvent>&) {}      // CallbackStyle::LegacyMode
0152     virtual void Process(const JEvent&) {}                             // CallbackStyle::ExpertMode
0153     virtual void Process(int32_t /*run_nr*/, uint64_t /*event_nr*/) {} // CallbackStyle::DeclarativeMode
0154     virtual void Finish() {}
0155 
0156 
0157 
0158     /// Access the encapsulated data, performing an upcast if necessary. This is useful for extracting data from
0159     /// all JFactories<T> where T extends a parent class S, such as JObject or TObject, in contexts where T is not known
0160     /// or it would introduce an unwanted coupling. The main application is for building DSTs.
0161     ///
0162     /// Be aware of the following caveats:
0163     /// - The factory's object type must not use virtual inheritance.
0164     /// - If JFactory::Process hasn't already been called, this will return an empty vector. This will NOT call JFactory::Process.
0165     /// - Someone must call JFactoryT<T>::EnableGetAs<S>, preferably the constructor. Otherwise, this will return an empty vector.
0166     /// - If S isn't a base class of T, this will return an empty vector.
0167     template<typename S>
0168     std::vector<S*> GetAs();
0169 
0170 
0171 
0172     /// Create() calls JFactory::Init,BeginRun,Process in an invariant-preserving way without knowing the exact
0173     /// type of object contained. In order to access these objects when all you have is a JFactory*, use JFactory::GetAs().
0174     virtual void Create(const std::shared_ptr<const JEvent>& event);
0175     virtual void Create(const JEvent& event);
0176 
0177     void DoInit();
0178     void DoFinish();
0179     void Summarize(JComponentSummary& summary) const override;
0180 
0181     virtual void Set(const std::vector<JObject *>&) { throw JException("Not supported!"); }
0182 
0183 
0184 protected:
0185 
0186     bool mRegenerate = false;
0187     bool mWriteToOutput = true;
0188     bool mPersistent = false;
0189 
0190     int32_t mPreviousRunNumber = -1;
0191     bool mInsideCreate = false; // Use this to detect cycles in factory dependencies
0192     std::unordered_map<std::type_index, std::unique_ptr<JAny>> mUpcastVTable;
0193     std::string mObjectName;
0194 
0195     mutable Status mStatus = Status::Uninitialized;
0196     mutable JCallGraphRecorder::JDataOrigin m_insert_origin = JCallGraphRecorder::ORIGIN_NOT_AVAILABLE; // (see note at top of JCallGraphRecorder.h)
0197 
0198     CreationStatus mCreationStatus = CreationStatus::NotCreatedYet;
0199 };
0200 
0201 // Because C++ doesn't support templated virtual functions, we implement our own dispatch table, mUpcastVTable.
0202 // This means that the JFactoryT is forced to manually populate this table by calling JFactoryT<T>::EnableGetAs.
0203 // We have the option to make the vtable be a static member of JFactoryT<T>, but we have chosen not to because:
0204 //
0205 //   1. It would be inconsistent with the fact that the user is supposed to call EnableGetAs in the ctor
0206 //   2. People in the future may want to generalize GetAs to support user-defined S* -> T* conversions (which I don't recommend)
0207 //   3. The size of the vtable is expected to be very small (<10 elements, most likely 2)
0208 
0209 template<typename S>
0210 std::vector<S*> JFactory::GetAs() {
0211     std::vector<S*> results;
0212     auto ti = std::type_index(typeid(S));
0213     auto search = mUpcastVTable.find(ti);
0214     if (search != mUpcastVTable.end()) {
0215         using upcast_fn_t = std::function<std::vector<S*>()>;
0216         auto temp = static_cast<JAnyT<upcast_fn_t>*>(&(*search->second));
0217         upcast_fn_t upcast_fn = temp->t;
0218         results = upcast_fn();
0219     }
0220     return results;
0221 }
0222 
0223