Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:01:41

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