Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-06 08:57:19

0001 
0002 // Copyright 2023, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 
0006 #pragma once
0007 
0008 #include <JANA/JFactoryT.h>
0009 #include <podio/Frame.h>
0010 
0011 /// The point of this additional base class is to allow us _untyped_ access to the underlying PODIO collection,
0012 /// at the cost of some weird multiple inheritance. The JEvent can trigger the untyped factory using Create(), then
0013 ///
0014 class JFactoryPodio {
0015 protected:
0016     const podio::CollectionBase* mCollection = nullptr;
0017     bool mIsSubsetCollection = false;
0018     podio::Frame* mFrame = nullptr;
0019 
0020 private:
0021     // Meant to be called internally, from JMultifactory
0022     friend class JMultifactory;
0023     void SetFrame(podio::Frame* frame) { mFrame = frame; }
0024 
0025 public:
0026     // Meant to be called from JEvent or VariadicPodioInput
0027     const podio::CollectionBase* GetCollection() { return mCollection; }
0028 
0029     // Meant to be called from ctor, or externally, if we are creating a dummy factory such as a multifactory helper
0030     void SetSubsetCollection(bool isSubsetCollection=true) { mIsSubsetCollection = isSubsetCollection; }
0031 };
0032 
0033 
0034 template <typename T>
0035 class JFactoryPodioT : public JFactoryT<T>, public JFactoryPodio {
0036 public:
0037     using CollectionT = typename T::collection_type;
0038 private:
0039     // mCollection is owned by the frame.
0040     // mFrame is owned by the JFactoryT<podio::Frame>.
0041     // mData holds lightweight value objects which hold a pointer into mCollection.
0042     // This factory owns these value objects.
0043 
0044 public:
0045     explicit JFactoryPodioT();
0046     ~JFactoryPodioT() override;
0047 
0048     void Init() override {}
0049     void BeginRun(const std::shared_ptr<const JEvent>&) override {}
0050     void ChangeRun(const std::shared_ptr<const JEvent>&) override {}
0051     void Process(const std::shared_ptr<const JEvent>&) override {}
0052     void EndRun() override {}
0053     void Finish() override {}
0054 
0055     void Create(const std::shared_ptr<const JEvent>& event) final;
0056     void Create(const JEvent& event) final;
0057 
0058     std::type_index GetObjectType() const final { return std::type_index(typeid(T)); }
0059     std::size_t GetNumObjects() const final { return mCollection->size(); }
0060     void ClearData() final;
0061 
0062     void SetCollection(CollectionT&& collection);
0063     void SetCollection(std::unique_ptr<CollectionT> collection);
0064     void Set(const std::vector<T*>& aData) final;
0065     void Set(std::vector<T*>&& aData) final;
0066     void Insert(T* aDatum) final;
0067 
0068 
0069 
0070 private:
0071     // This is meant to be called by JEvent::Insert
0072     friend class JEvent;
0073     void SetCollectionAlreadyInFrame(const CollectionT* collection);
0074 
0075 };
0076 
0077 
0078 template <typename T>
0079 JFactoryPodioT<T>::JFactoryPodioT() = default;
0080 
0081 template <typename T>
0082 JFactoryPodioT<T>::~JFactoryPodioT() {
0083     // Ownership of mData, mCollection, and mFrame is complicated, so we always handle it via ClearData()
0084     ClearData();
0085 }
0086 
0087 template <typename T>
0088 void JFactoryPodioT<T>::SetCollection(CollectionT&& collection) {
0089     /// Provide a PODIO collection. Note that PODIO assumes ownership of this collection, and the
0090     /// collection pointer should be assumed to be invalid after this call
0091 
0092     if (this->mFrame == nullptr) {
0093         throw JException("JFactoryPodioT: Unable to add collection to frame as frame is missing!");
0094     }
0095     const auto& moved = this->mFrame->put(std::move(collection), this->GetTag());
0096     this->mCollection = &moved;
0097 
0098     for (const T& item : moved) {
0099         T* clone = new T(item);
0100         this->mData.push_back(clone);
0101     }
0102     this->mStatus = JFactory::Status::Inserted;
0103     this->mCreationStatus = JFactory::CreationStatus::Inserted;
0104 }
0105 
0106 
0107 template <typename T>
0108 void JFactoryPodioT<T>::SetCollection(std::unique_ptr<CollectionT> collection) {
0109     /// Provide a PODIO collection. Note that PODIO assumes ownership of this collection, and the
0110     /// collection pointer should be assumed to be invalid after this call
0111 
0112     if (this->mFrame == nullptr) {
0113         throw JException("JFactoryPodioT: Unable to add collection to frame as frame is missing!");
0114     }
0115     this->mFrame->put(std::move(collection), this->GetTag());
0116     const auto* moved = &this->mFrame->template get<CollectionT>(this->GetTag());
0117     this->mCollection = moved;
0118 
0119     for (const T& item : *moved) {
0120         T* clone = new T(item);
0121         this->mData.push_back(clone);
0122     }
0123     this->mStatus = JFactory::Status::Inserted;
0124     this->mCreationStatus = JFactory::CreationStatus::Inserted;
0125 }
0126 
0127 
0128 template <typename T>
0129 void JFactoryPodioT<T>::ClearData() {
0130     if (this->mStatus == JFactory::Status::Uninitialized) {
0131         return;
0132     }
0133     for (auto p : this->mData) {
0134       // Avoid potentially invalid call to ObjBase::release(). The frame and
0135       // all the collections and all Obj may have been deallocated at this point.
0136       p->unlink();
0137       delete p;
0138     }
0139     this->mData.clear();
0140     this->mCollection = nullptr;  // Collection is owned by the Frame, so we ignore here
0141     this->mFrame = nullptr;  // Frame is owned by the JEvent, so we ignore here
0142     this->mStatus = JFactory::Status::Unprocessed;
0143     this->mCreationStatus = JFactory::CreationStatus::NotCreatedYet;
0144 }
0145 
0146 template <typename T>
0147 void JFactoryPodioT<T>::SetCollectionAlreadyInFrame(const CollectionT* collection) {
0148     for (const T& item : *collection) {
0149         T* clone = new T(item);
0150         this->mData.push_back(clone);
0151     }
0152     this->mCollection = collection;
0153     this->mStatus = JFactory::Status::Inserted;
0154     this->mCreationStatus = JFactory::CreationStatus::Inserted;
0155 }
0156 
0157 // This free function is used to break the dependency loop between JFactoryPodioT and JEvent.
0158 podio::Frame* GetOrCreateFrame(const JEvent& event);
0159 
0160 template <typename T>
0161 void JFactoryPodioT<T>::Create(const JEvent& event) {
0162     mFrame = GetOrCreateFrame(event);
0163     try {
0164         JFactory::Create(event);
0165     }
0166     catch (...) {
0167         if (mCollection == nullptr) {
0168             // If calling Create() excepts, we still create an empty collection
0169             // so that podio::ROOTWriter doesn't segfault on the null mCollection pointer
0170             SetCollection(CollectionT());
0171         }
0172         throw;
0173     }
0174     if (mCollection == nullptr) {
0175         SetCollection(CollectionT());
0176         // If calling Process() didn't result in a call to Set() or SetCollection(), we create an empty collection
0177         // so that podio::ROOTWriter doesn't segfault on the null mCollection pointer
0178     }
0179 }
0180 
0181 template <typename T>
0182 void JFactoryPodioT<T>::Create(const std::shared_ptr<const JEvent>& event) {
0183     Create(*event);
0184 }
0185 
0186 template <typename T>
0187 void JFactoryPodioT<T>::Set(const std::vector<T*>& aData) {
0188     CollectionT collection;
0189     if (mIsSubsetCollection) collection.setSubsetCollection(true);
0190     for (T* item : aData) {
0191         collection.push_back(*item);
0192         delete item;
0193     }
0194     SetCollection(std::move(collection));
0195 }
0196 
0197 template <typename T>
0198 void JFactoryPodioT<T>::Set(std::vector<T*>&& aData) {
0199     CollectionT collection;
0200     if (mIsSubsetCollection) collection.setSubsetCollection(true);
0201     for (T* item : aData) {
0202         collection.push_back(*item);
0203         delete item;
0204     }
0205     SetCollection(std::move(collection));
0206 }
0207 
0208 template <typename T>
0209 void JFactoryPodioT<T>::Insert(T* aDatum) {
0210     CollectionT collection;
0211     if (mIsSubsetCollection) collection->setSubsetCollection(true);
0212     collection->push_back(*aDatum);
0213     delete aDatum;
0214     SetCollection(std::move(collection));
0215 }
0216