Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /jana2/src/libraries/JANA/Components/JDatabundle.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright 2024, Jefferson Science Associates, LLC.
0002 // Subject to the terms in the LICENSE file found in the top-level directory.
0003 
0004 #pragma once
0005 
0006 #include <JANA/Utils/JAny.h>
0007 #include <JANA/Utils/JCallGraphRecorder.h>
0008 
0009 #include <string>
0010 #include <functional>
0011 #include <typeindex>
0012 #include <vector>
0013 #include <memory>
0014 #include <unordered_map>
0015 //#include <optional>
0016 
0017 
0018 class JFactory;
0019 
0020 class JDatabundle {
0021 public:
0022     // Typedefs
0023     enum class Status { Empty, Created, Inserted, InsertedViaGetObjects };
0024 
0025 private:
0026     // Fields
0027     Status m_status = Status::Empty;
0028     std::string m_unique_name;
0029     std::string m_short_name;
0030     bool m_has_short_name = true;
0031     std::string m_type_name;
0032     JFactory* m_factory = nullptr;
0033     //std::optional<std::type_index> m_inner_type_index;
0034     mutable JCallGraphRecorder::JDataOrigin m_insert_origin = JCallGraphRecorder::ORIGIN_NOT_AVAILABLE;
0035 
0036 
0037 protected:
0038     std::unordered_map<std::type_index, std::unique_ptr<JAny>> mUpcastVTable;
0039 
0040 public:
0041     // Interface
0042     JDatabundle() = default;
0043     virtual ~JDatabundle() = default;
0044     virtual size_t GetSize() const = 0;
0045     virtual void ClearData() = 0;
0046 
0047     // Getters
0048     Status GetStatus() const { return m_status; }
0049     std::string GetUniqueName() const { return m_unique_name; }
0050     std::string GetShortName() const { return m_short_name; }
0051     bool HasShortName() const { return m_has_short_name; }
0052     std::string GetTypeName() const { return m_type_name; }
0053     //std::optional<std::type_index> GetTypeIndex() const { return m_inner_type_index; }
0054     JCallGraphRecorder::JDataOrigin GetInsertOrigin() const { return m_insert_origin; } ///< If objects were placed here by JEvent::Insert() this records whether that call was made from a source or factory.
0055     JFactory* GetFactory() const { return m_factory; }
0056 
0057     // Setters
0058     void SetStatus(Status s) { m_status = s;}
0059     void SetUniqueName(std::string unique_name) { m_unique_name = unique_name; m_has_short_name = false; }
0060     void SetShortName(std::string short_name) {
0061         m_short_name = short_name;
0062         if (m_short_name.empty()) {
0063             m_unique_name = m_type_name;
0064         }
0065         else {
0066             m_unique_name = m_type_name + ":" + short_name;
0067         }
0068         m_has_short_name = true;
0069     }
0070     void SetTypeName(std::string type_name) { m_type_name = type_name; }
0071     void SetInsertOrigin(JCallGraphRecorder::JDataOrigin origin) { m_insert_origin = origin; } ///< Called automatically by JEvent::Insert() to records whether that call was made by a source or factory.
0072     void SetFactory(JFactory* fac) { m_factory = fac; }
0073 
0074     // Templates 
0075     //
0076     /// Generically access the encapsulated data, performing an upcast if necessary. This is useful for extracting data from
0077     /// all JFactories<T> where T extends a parent class S, such as JObject or TObject, in contexts where T is not known
0078     /// or it would introduce an unwanted coupling. The main application is for building DSTs.
0079     ///
0080     /// Be aware of the following caveats:
0081     /// - The factory's object type must not use virtual inheritance.
0082     /// - If JFactory::Process hasn't already been called, this will return an empty vector. This will NOT call JFactory::Process.
0083     /// - Someone must call JFactoryT<T>::EnableGetAs<S>, preferably the constructor. Otherwise, this will return an empty vector.
0084     /// - If S isn't a base class of T, this will return an empty vector.
0085     template<typename S>
0086     std::vector<S*> GetAs();
0087 
0088 };
0089 
0090 
0091 
0092 // Because C++ doesn't support templated virtual functions, we implement our own dispatch table, mUpcastVTable.
0093 // This means that the JFactoryT is forced to manually populate this table by calling JFactoryT<T>::EnableGetAs.
0094 // We have the option to make the vtable be a static member of JFactoryT<T>, but we have chosen not to because:
0095 //
0096 //   1. It would be inconsistent with the fact that the user is supposed to call EnableGetAs in the ctor
0097 //   2. People in the future may want to generalize GetAs to support user-defined S* -> T* conversions (which I don't recommend)
0098 //   3. The size of the vtable is expected to be very small (<10 elements, most likely 2)
0099 
0100 template<typename S>
0101 std::vector<S*> JDatabundle::GetAs() {
0102     std::vector<S*> results;
0103     auto ti = std::type_index(typeid(S));
0104     auto search = mUpcastVTable.find(ti);
0105     if (search != mUpcastVTable.end()) {
0106         using upcast_fn_t = std::function<std::vector<S*>()>;
0107         auto temp = static_cast<JAnyT<upcast_fn_t>*>(&(*search->second));
0108         upcast_fn_t upcast_fn = temp->t;
0109         results = upcast_fn();
0110     }
0111     return results;
0112 }
0113 
0114