Back to home page

EIC code displayed by LXR

 
 

    


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

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