|
||||
File indexing completed on 2025-01-18 10:17:38
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
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |