Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-08-04 22:45:02

0001 #ifndef FWCore_Framework_UnscheduledCallProducer_h
0002 #define FWCore_Framework_UnscheduledCallProducer_h
0003 
0004 // -*- C++ -*-
0005 //
0006 // Package:     FWCore/Framework
0007 // Class  :     UnscheduledCallProducer
0008 //
0009 /**\class UnscheduledCallProducer UnscheduledCallProducer.h "UnscheduledCallProducer.h"
0010 
0011  Description: Handles calling of EDProducers which are unscheduled
0012 
0013  Usage:
0014  <usage>
0015 
0016  */
0017 
0018 #include "FWCore/Framework/interface/BranchActionType.h"
0019 #include "FWCore/Framework/interface/Frameworkfwd.h"
0020 #include "FWCore/Framework/interface/OccurrenceTraits.h"
0021 #include "FWCore/Framework/interface/maker/Worker.h"
0022 #include "FWCore/Framework/interface/UnscheduledAuxiliary.h"
0023 #include "FWCore/Concurrency/interface/WaitingTaskHolder.h"
0024 #include "FWCore/ServiceRegistry/interface/ParentContext.h"
0025 #include "FWCore/ServiceRegistry/interface/ActivityRegistry.h"
0026 
0027 #include <vector>
0028 #include <unordered_map>
0029 #include <string>
0030 #include <sstream>
0031 #include <cassert>
0032 
0033 namespace edm {
0034 
0035   class EventTransitionInfo;
0036   class ModuleCallingContext;
0037 
0038   class UnscheduledCallProducer {
0039   public:
0040     using worker_container = std::vector<Worker*>;
0041     using const_iterator = worker_container::const_iterator;
0042 
0043     UnscheduledCallProducer(ActivityRegistry& iReg) : unscheduledWorkers_() {
0044       aux_.preModuleDelayedGetSignal_.connect(std::cref(iReg.preModuleEventDelayedGetSignal_));
0045       aux_.postModuleDelayedGetSignal_.connect(std::cref(iReg.postModuleEventDelayedGetSignal_));
0046     }
0047     void addWorker(Worker* aWorker) {
0048       assert(nullptr != aWorker);
0049       unscheduledWorkers_.push_back(aWorker);
0050       if (aWorker->hasAccumulator()) {
0051         accumulatorWorkers_.push_back(aWorker);
0052       }
0053     }
0054 
0055     void removeWorker(Worker const* worker) {
0056       unscheduledWorkers_.erase(std::remove(unscheduledWorkers_.begin(), unscheduledWorkers_.end(), worker),
0057                                 unscheduledWorkers_.end());
0058       accumulatorWorkers_.erase(std::remove(accumulatorWorkers_.begin(), accumulatorWorkers_.end(), worker),
0059                                 accumulatorWorkers_.end());
0060     }
0061 
0062     void setEventTransitionInfo(EventTransitionInfo const& info) { aux_.setEventTransitionInfo(info); }
0063 
0064     UnscheduledAuxiliary const& auxiliary() const { return aux_; }
0065 
0066     const_iterator begin() const { return unscheduledWorkers_.begin(); }
0067     const_iterator end() const { return unscheduledWorkers_.end(); }
0068     worker_container const& workers() const { return unscheduledWorkers_; }
0069 
0070     template <typename T, typename U>
0071     void runNowAsync(WaitingTaskHolder task,
0072                      typename T::TransitionInfoType const& info,
0073                      ServiceToken const& token,
0074                      StreamID streamID,
0075                      typename T::Context const* topContext,
0076                      U const* context) const {
0077       //do nothing for event since we will run when requested
0078       if (!T::isEvent_) {
0079         for (auto worker : unscheduledWorkers_) {
0080           ParentContext parentContext(context);
0081 
0082           // We do not need to run prefetching here because this only handles
0083           // stream transitions for runs and lumis. There are no products put
0084           // into the runs or lumis in stream transitions, so there can be
0085           // no data dependencies which require prefetching. Prefetching is
0086           // needed for global transitions, but they are run elsewhere.
0087           worker->doWorkNoPrefetchingAsync<T>(task, info, token, streamID, parentContext, topContext);
0088         }
0089       }
0090     }
0091 
0092     template <typename T>
0093     void runAccumulatorsAsync(WaitingTaskHolder task,
0094                               typename T::TransitionInfoType const& info,
0095                               ServiceToken const& token,
0096                               StreamID streamID,
0097                               ParentContext const& parentContext,
0098                               typename T::Context const* context) {
0099       for (auto worker : accumulatorWorkers_) {
0100         worker->doWorkAsync<T>(task, info, token, streamID, parentContext, context);
0101       }
0102     }
0103 
0104   private:
0105     template <typename T, typename ID>
0106     void addContextToException(cms::Exception& ex, Worker const* worker, ID const& id) const {
0107       std::ostringstream ost;
0108       ost << "Processing " << T::transitionName() << " " << id;
0109       ex.addContext(ost.str());
0110     }
0111     worker_container unscheduledWorkers_;
0112     worker_container accumulatorWorkers_;
0113     UnscheduledAuxiliary aux_;
0114   };
0115 
0116 }  // namespace edm
0117 
0118 #endif