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