Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:17:39

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 
0016 #if JANA2_HAVE_ROOT
0017 #include <TObject.h>
0018 #endif
0019 
0020 
0021 template<typename T>
0022 class JFactoryT : public JFactory {
0023 public:
0024 
0025     using IteratorType = typename std::vector<T*>::const_iterator;
0026     using PairType = std::pair<IteratorType, IteratorType>;
0027 
0028     JFactoryT(std::string tag="") : JFactory(JTypeInfo::demangle<T>(), tag){
0029         EnableGetAs<T>();
0030         EnableGetAs<JObject>( std::is_convertible<T,JObject>() ); // Automatically add JObject if this can be converted to it
0031 #if JANA2_HAVE_ROOT
0032         EnableGetAs<TObject>( std::is_convertible<T,TObject>() ); // Automatically add TObject if this can be converted to it
0033 #endif
0034     }
0035 
0036     ~JFactoryT() override = default;
0037 
0038     void Init() override {}
0039     void BeginRun(const std::shared_ptr<const JEvent>&) override {}
0040     void ChangeRun(const std::shared_ptr<const JEvent>&) override {}
0041     void EndRun() override {}
0042     void Process(const std::shared_ptr<const JEvent>&) override {}
0043 
0044 
0045     std::type_index GetObjectType(void) const override {
0046         return std::type_index(typeid(T));
0047     }
0048 
0049     std::size_t GetNumObjects(void) const override {
0050         return mData.size();
0051     }
0052 
0053     /// CreateAndGetData handles all the preconditions and postconditions involved in calling the user-defined Open(),
0054     /// ChangeRun(), and Process() methods. These include making sure the JFactory JApplication is set, Init() is called
0055     /// exactly once, exceptions are tagged with the originating plugin and eventsource, ChangeRun() is
0056     /// called if and only if the run number changes, etc.
0057     PairType CreateAndGetData(const std::shared_ptr<const JEvent>& event) {
0058         Create(event);
0059         return std::make_pair(mData.cbegin(), mData.cend());
0060     }
0061 
0062     // Retrieve a const reference to the data directly (no copying!)
0063     const std::vector<T*>& GetData() {
0064         return mData;
0065     }
0066 
0067     /// Please use the typed setters instead whenever possible
0068     // TODO: Deprecate this!
0069     void Set(const std::vector<JObject*>& aData) override {
0070         std::vector<T*> data;
0071         for (auto obj : aData) {
0072             T* casted = dynamic_cast<T*>(obj);
0073             assert(casted != nullptr);
0074             data.push_back(casted);
0075         }
0076         Set(std::move(data));
0077     }
0078 
0079     /// Please use the typed setters instead whenever possible
0080     // TODO: Deprecate this!
0081     void Insert(JObject* aDatum) override {
0082         T* casted = dynamic_cast<T*>(aDatum);
0083         assert(casted != nullptr);
0084         Insert(casted);
0085     }
0086 
0087     virtual void Set(const std::vector<T*>& aData) {
0088         if (aData == mData) {
0089             // The user populated mData directly instead of populating a temporary vector and passing it to us.
0090             // Doing this breaks the JFactory::Status invariant unless they remember to call Set() afterwards.
0091             // Ideally, they would use a temporary vector and not access mData at all, but they are used to this
0092             // from JANA1 and I haven't found a cleaner solution that gives them what they want yet.
0093             mStatus = Status::Inserted;
0094             mCreationStatus = CreationStatus::Inserted;
0095         }
0096         else {
0097             ClearData();
0098             mData = aData;
0099             mStatus = Status::Inserted;
0100             mCreationStatus = CreationStatus::Inserted;
0101         }
0102     }
0103 
0104     virtual void Set(std::vector<T*>&& aData) {
0105         ClearData();
0106         mData = std::move(aData);
0107         mStatus = Status::Inserted;
0108         mCreationStatus = CreationStatus::Inserted;
0109     }
0110 
0111     virtual void Insert(T* aDatum) {
0112         mData.push_back(aDatum);
0113         mStatus = Status::Inserted;
0114         mCreationStatus = CreationStatus::Inserted;
0115     }
0116 
0117 
0118     /// EnableGetAs generates a vtable entry so that users may extract the
0119     /// contents of this JFactoryT from the type-erased JFactory. The user has to manually specify which upcasts
0120     /// to allow, and they have to do so for each instance. It is recommended to do so in the constructor.
0121     /// Note that EnableGetAs<T>() is called automatically.
0122     template <typename S> void EnableGetAs ();
0123 
0124     // The following specializations allow automatically adding standard types (e.g. JObject) using things like
0125     // std::is_convertible(). The std::true_type version defers to the standard EnableGetAs().
0126     template <typename S> void EnableGetAs(std::true_type) { EnableGetAs<S>(); }
0127     template <typename S> void EnableGetAs(std::false_type) {}
0128 
0129     void ClearData() override {
0130 
0131         // ClearData won't do anything if Init() hasn't been called
0132         if (mStatus == Status::Uninitialized) {
0133             return;
0134         }
0135         // ClearData() does nothing if persistent flag is set.
0136         // User must manually recycle data, e.g. during ChangeRun()
0137         if (TestFactoryFlag(JFactory_Flags_t::PERSISTENT)) {
0138             return;
0139         }
0140 
0141         // Assuming we _are_ the object owner, delete the underlying jobjects
0142         if (!TestFactoryFlag(JFactory_Flags_t::NOT_OBJECT_OWNER)) {
0143             for (auto p : mData) delete p;
0144         }
0145         mData.clear();
0146         mStatus = Status::Unprocessed;
0147         mCreationStatus = CreationStatus::NotCreatedYet;
0148     }
0149 
0150 
0151 protected:
0152     std::vector<T*> mData;
0153 };
0154 
0155 template<typename T>
0156 template<typename S>
0157 void JFactoryT<T>::EnableGetAs() {
0158 
0159     auto upcast_lambda = [this]() {
0160         std::vector<S*> results;
0161         for (auto t : mData) {
0162             results.push_back(static_cast<S*>(t));
0163         }
0164         return results;
0165     };
0166 
0167     auto key = std::type_index(typeid(S));
0168     using upcast_fn_t = std::function<std::vector<S*>()>;
0169     mUpcastVTable[key] = std::unique_ptr<JAny>(new JAnyT<upcast_fn_t>(std::move(upcast_lambda)));
0170 }
0171 
0172