Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-15 09:15:55

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 <vector>
0008 #include <type_traits>
0009 
0010 #include <JANA/JApplication.h>
0011 #include <JANA/JFactory.h>
0012 #include <JANA/JObject.h>
0013 #include <JANA/JVersion.h>
0014 #include <JANA/Utils/JTypeInfo.h>
0015 #include <JANA/Components/JLightweightOutput.h>
0016 
0017 #if JANA2_HAVE_ROOT
0018 #include <TObject.h>
0019 #endif
0020 
0021 
0022 template<typename T>
0023 class JFactoryT : public JFactory {
0024 public:
0025 
0026     using IteratorType = typename std::vector<T*>::const_iterator;
0027     using PairType = std::pair<IteratorType, IteratorType>;
0028 
0029     JFactoryT(std::string tag="") {
0030         mOutput.GetDatabundle().AttachData(&mData);
0031         SetTag(tag);
0032         SetPrefix(mOutput.GetDatabundle().GetUniqueName());
0033         SetObjectName(mOutput.GetDatabundle().GetTypeName());
0034 
0035         EnableGetAs<T>();
0036         EnableGetAs<JObject>( std::is_convertible<T,JObject>() ); // Automatically add JObject if this can be converted to it
0037 #if JANA2_HAVE_ROOT
0038         EnableGetAs<TObject>( std::is_convertible<T,TObject>() ); // Automatically add TObject if this can be converted to it
0039 #endif
0040     }
0041 
0042     ~JFactoryT() override = default;
0043 
0044     void Init() override {}
0045     void BeginRun(const std::shared_ptr<const JEvent>&) override {}
0046     void ChangeRun(const std::shared_ptr<const JEvent>&) override {}
0047     void EndRun() override {}
0048     void Process(const std::shared_ptr<const JEvent>&) override {}
0049 
0050 
0051     void SetTag(std::string tag) { mOutput.SetShortName(tag); }
0052 
0053     std::type_index GetObjectType(void) const override {
0054         return std::type_index(typeid(T));
0055     }
0056 
0057     std::size_t GetNumObjects(void) const override {
0058         return mData.size();
0059     }
0060 
0061     /// CreateAndGetData handles all the preconditions and postconditions involved in calling the user-defined Open(),
0062     /// ChangeRun(), and Process() methods. These include making sure the JFactory JApplication is set, Init() is called
0063     /// exactly once, exceptions are tagged with the originating plugin and eventsource, ChangeRun() is
0064     /// called if and only if the run number changes, etc.
0065     PairType CreateAndGetData(const std::shared_ptr<const JEvent>& event) {
0066         Create(*event.get());
0067         return std::make_pair(mData.cbegin(), mData.cend());
0068     }
0069 
0070     PairType CreateAndGetData(const JEvent& event) {
0071         Create(event);
0072         return std::make_pair(mData.cbegin(), mData.cend());
0073     }
0074 
0075     // Retrieve a const reference to the data directly (no copying!)
0076     const std::vector<T*>& GetData() {
0077         return mData;
0078     }
0079 
0080     /// Please use the typed setters instead whenever possible
0081     [[deprecated]]
0082     void Set(const std::vector<JObject*>& aData) override {
0083         std::vector<T*> data;
0084         for (auto obj : aData) {
0085             T* casted = dynamic_cast<T*>(obj);
0086             assert(casted != nullptr);
0087             data.push_back(casted);
0088         }
0089         Set(std::move(data));
0090     }
0091 
0092     /// Please use the typed setters instead whenever possible
0093     [[deprecated]]
0094     void Insert(JObject* aDatum) override {
0095         T* casted = dynamic_cast<T*>(aDatum);
0096         assert(casted != nullptr);
0097         Insert(casted);
0098     }
0099 
0100     virtual void Set(const std::vector<T*>& aData) {
0101         if (aData == mData) {
0102             // The user populated mData directly instead of populating a temporary vector and passing it to us.
0103             // Doing this breaks the JFactory::Status invariant unless they remember to call Set() afterwards.
0104             // Ideally, they would use a temporary vector and not access mData at all, but they are used to this
0105             // from JANA1 and I haven't found a cleaner solution that gives them what they want yet.
0106             mStatus = Status::Inserted;
0107             mCreationStatus = CreationStatus::Inserted;
0108         }
0109         else {
0110             ClearData();
0111             mData = aData;
0112             mStatus = Status::Inserted;
0113             mCreationStatus = CreationStatus::Inserted;
0114         }
0115     }
0116 
0117     virtual void Set(std::vector<T*>&& aData) {
0118         ClearData();
0119         mData = std::move(aData);
0120         mStatus = Status::Inserted;
0121         mCreationStatus = CreationStatus::Inserted;
0122     }
0123 
0124     virtual void Insert(T* aDatum) {
0125         mData.push_back(aDatum);
0126         mStatus = Status::Inserted;
0127         mCreationStatus = CreationStatus::Inserted;
0128     }
0129 
0130     /// Set a flag (or flags)
0131     inline void SetFactoryFlag(JFactory_Flags_t f) override {
0132         switch (f) {
0133             case JFactory::PERSISTENT: SetPersistentFlag(true); break;
0134             case JFactory::NOT_OBJECT_OWNER: SetNotOwnerFlag(true); break;
0135             case JFactory::REGENERATE: SetRegenerateFlag(true); break;
0136             case JFactory::WRITE_TO_OUTPUT: SetWriteToOutputFlag(true); break;
0137             default: throw JException("Invalid factory flag");
0138         }
0139     }
0140 
0141     /// Clear a flag (or flags)
0142     inline void ClearFactoryFlag(JFactory_Flags_t f) {
0143         switch (f) {
0144             case JFactory::PERSISTENT: SetPersistentFlag(false); break;
0145             case JFactory::NOT_OBJECT_OWNER: SetNotOwnerFlag(false); break;
0146             case JFactory::REGENERATE: SetRegenerateFlag(false); break;
0147             case JFactory::WRITE_TO_OUTPUT: SetWriteToOutputFlag(false); break;
0148             default: throw JException("Invalid factory flag");
0149         }
0150     }
0151 
0152     inline void SetPersistentFlag(bool persistent) {
0153         mOutput.GetDatabundle().SetPersistentFlag(persistent);
0154     }
0155 
0156     inline void SetNotOwnerFlag(bool not_owner) {
0157         mOutput.GetDatabundle().SetNotOwnerFlag(not_owner);
0158     }
0159 
0160 
0161 
0162     /// EnableGetAs generates a vtable entry so that users may extract the
0163     /// contents of this JFactoryT from the type-erased JFactory. The user has to manually specify which upcasts
0164     /// to allow, and they have to do so for each instance. It is recommended to do so in the constructor.
0165     /// Note that EnableGetAs<T>() is called automatically.
0166     template <typename S> void EnableGetAs ();
0167 
0168     // The following specializations allow automatically adding standard types (e.g. JObject) using things like
0169     // std::is_convertible(). The std::true_type version defers to the standard EnableGetAs().
0170     template <typename S> void EnableGetAs(std::true_type) { EnableGetAs<S>(); }
0171     template <typename S> void EnableGetAs(std::false_type) {}
0172 
0173     void ClearData() override {
0174         // This is mainly used for test cases now. JFactorySet::Clear directly clears all databundles, 
0175         // even those without a corresponding JFactory.
0176 
0177         if (mStatus == Status::Uninitialized) {
0178             // ClearData won't do anything if Init() hasn't been called
0179             return;
0180         }
0181         mStatus = Status::Unprocessed;
0182         mCreationStatus = CreationStatus::NotCreatedYet;
0183         for (auto* output : GetDatabundleOutputs()) {
0184             for (auto* db : output->GetDatabundles()) {
0185                 db->ClearData();
0186             }
0187         }
0188     }
0189 
0190 
0191 protected:
0192     jana::components::Output<T> mOutput {this};
0193     std::vector<T*> mData;
0194 };
0195 
0196 template<typename T>
0197 template<typename S>
0198 void JFactoryT<T>::EnableGetAs() {
0199 
0200     auto upcast_lambda = [this]() {
0201         std::vector<S*> results;
0202         for (auto t : mData) {
0203             results.push_back(static_cast<S*>(t));
0204         }
0205         return results;
0206     };
0207 
0208     auto key = std::type_index(typeid(S));
0209     using upcast_fn_t = std::function<std::vector<S*>()>;
0210     mUpcastVTable[key] = std::unique_ptr<JAny>(new JAnyT<upcast_fn_t>(std::move(upcast_lambda)));
0211 }
0212 
0213