Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:01:41

0001 
0002 #pragma once
0003 #include <mutex>
0004 
0005 #include <JANA/JEventProcessor.h>
0006 
0007 /// This class can be used to safely implement sequential code while ensuring
0008 /// the factory algorithms are run in parallel.
0009 ///
0010 /// n.b. If you need to run sequentially to serialize operation with ROOT
0011 /// then please use the JEventProcessorSequentialROOT class instead.
0012 ///
0013 /// This is a specialized version of JEventProcessor that allows data types
0014 /// that will be needed to be specified in the subclass definition. The
0015 /// types will be prefetched via event->Get() calls and then a mutex locked
0016 /// prior to calling the ProcessSequential method. The types are specified
0017 /// by adding PrefetchT data members to the class as illustrated in the
0018 /// example below.
0019 ///
0020 /// class DaveTestProcessor: public JEventProcessorSequential {
0021 ///
0022 ///  public:
0023 ///
0024 ///     // These declare object types that should be automatically fetched
0025 ///     // from the event before ProcessSequential is called.
0026 ///     PrefetchT<Hit>     hits     = {this};
0027 ///     PrefetchT<Cluster> clusters = {this, "MyTag"};
0028 ///
0029 ///     // This will be run sequentially
0030 ///     void ProcessSequential(const std::shared_ptr<const JEvent>& event) override {
0031 ///
0032 ///         // Do NOT call event->Get() here!
0033 ///
0034 ///         // The hits and clusters objects will already be filled by calls
0035 ///         // to event->Get(). Just use them here via their operator().
0036 ///         for( auto h : hits() ){
0037 ///             // h is const Hit*
0038 ///         }
0039 ///     }
0040 ///
0041 ///     // Boilerplate stuff
0042 ///     DaveTestProcessor() { SetTypeName(NAME_OF_THIS); }
0043 ///     void Init() override {}
0044 ///     void Finish() override {}
0045 ///  };
0046 ///
0047 class JEventProcessorSequential : public JEventProcessor {
0048     // This works in the following way:
0049     //
0050     // Two utility classes are defined here: Prefetch and PrefetchT with the
0051     // latter being a template. Subclasses can add any number of data members
0052     // of type PrefetchT. Using initializers, a list of the Prefetch members
0053     // is stored in the JEventProcessorSequential object itself.
0054     //
0055     // The Process method here loops over the Prefetch members calling
0056     // event->Get() for each and storing the resulting vector<const *T>
0057     // in the Prefetch member object. It then locks its own mutex before
0058     // calling ProcessSequential().
0059     //
0060     // The Process method is defined here and marked as "final" so subclasses
0061     // may not overide it. Instead, a new virtual method, ProcessSequential,
0062     // is added that the user may override.
0063     //
0064     // The tricky business here is capturing a list of the Prefetch data
0065     // members so they can be looped over at run time. Thus, the strange syntax
0066     // of passing the "this" argument to the PrefetchT constructors.
0067     // Similarly, each Prefetch object passes its "this" pointer back to the
0068     // JEventProcessorSequential object that owns it.
0069 
0070 public:
0071 
0072     JEventProcessorSequential(){}
0073     virtual ~JEventProcessorSequential() = default;
0074 
0075     // non-templated base class
0076     class Prefetch{
0077     public:
0078         virtual void Get(const std::shared_ptr<const JEvent>& event) = 0;
0079         virtual void Fill(const std::shared_ptr<const JEvent>& event) = 0;
0080     };
0081 
0082     // typed class
0083     template<typename T>
0084     class PrefetchT:public Prefetch{
0085     public:
0086         // This constructor gets called by the {this} initializer for the data member.
0087         PrefetchT(JEventProcessorSequential *jeps, const std::string &tag=""):mTag(tag){jeps->mPrefetch.push_back(this);}
0088 
0089         std::vector<const T*>& operator()(){ return mObjs; }
0090         void Get(const std::shared_ptr<const JEvent>& event){ event->Get<T>(mTag); }
0091         void Fill(const std::shared_ptr<const JEvent>& event){ mObjs = event->Get<T>(mTag); }
0092 
0093     private:
0094         PrefetchT()=default; // user must pass "this" so member can be added to our mPrefetch
0095 
0096         std::string mTag;
0097         std::vector<const T*> mObjs;
0098     };
0099 
0100     // JEventProcessorSequential methods
0101     void Init() override {};
0102     void Finish() override {};
0103 
0104     void Process(const std::shared_ptr<const JEvent>& event) override final{
0105         for( auto p : mPrefetch ) p->Get(event);  // make sure all factories have been activated
0106         std::lock_guard<std::mutex> lck(mMutex);
0107         for( auto p : mPrefetch ) p->Fill(event); // Copy object pointers into members
0108         ProcessSequential( event );
0109     }
0110     virtual void ProcessSequential(const std::shared_ptr<const JEvent>& /*event*/){};
0111 
0112 private:
0113 
0114     std::vector<Prefetch*> mPrefetch;
0115     std::mutex mMutex;
0116 };
0117 
0118 
0119