Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-08-13 23:27:17

0001 
0002 /*----------------------------------------------------------------------
0003 
0004 Toy edm::stream::EDProducer modules of
0005 edm::*Cache templates and edm::*Producer classes
0006 for testing purposes only.
0007 
0008 ----------------------------------------------------------------------*/
0009 
0010 #include <atomic>
0011 #include <functional>
0012 #include <iostream>
0013 #include <map>
0014 #include <tuple>
0015 #include <unistd.h>
0016 #include <vector>
0017 
0018 #include "FWCore/Framework/interface/CacheHandle.h"
0019 #include "FWCore/Framework/interface/stream/EDProducer.h"
0020 #include "FWCore/Framework/interface/maker/WorkerT.h"
0021 #include "FWCore/Framework/interface/HistoryAppender.h"
0022 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0023 #include "FWCore/ServiceRegistry/interface/ParentContext.h"
0024 #include "FWCore/ServiceRegistry/interface/StreamContext.h"
0025 #include "FWCore/Utilities/interface/GlobalIdentifier.h"
0026 #include "FWCore/Framework/interface/Event.h"
0027 #include "FWCore/Framework/interface/MakerMacros.h"
0028 #include "FWCore/Framework/interface/ProcessBlock.h"
0029 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0030 #include "FWCore/Utilities/interface/EDMException.h"
0031 #include "DataFormats/TestObjects/interface/ToyProducts.h"
0032 
0033 namespace edmtest {
0034   namespace stream {
0035 
0036     // anonymous namespace here causes build warnings
0037     namespace cache {
0038       struct Cache {
0039         Cache() : value(0), run(0), lumi(0) {}
0040         //Using mutable since we want to update the value.
0041         mutable std::atomic<unsigned int> value;
0042         mutable std::atomic<unsigned int> run;
0043         mutable std::atomic<unsigned int> lumi;
0044       };
0045 
0046       struct UnsafeCache {
0047         UnsafeCache() : value(0), run(0), lumi(0) {}
0048         unsigned int value;
0049         unsigned int run;
0050         unsigned int lumi;
0051       };
0052 
0053       struct TestGlobalCache {
0054         CMS_THREAD_SAFE mutable edm::EDPutTokenT<unsigned int> token_;
0055         CMS_THREAD_SAFE mutable edm::EDGetTokenT<unsigned int> getTokenBegin_;
0056         CMS_THREAD_SAFE mutable edm::EDGetTokenT<unsigned int> getTokenEnd_;
0057         unsigned int trans_{0};
0058         mutable std::atomic<unsigned int> m_count{0};
0059       };
0060 
0061     }  // namespace cache
0062 
0063     using Cache = cache::Cache;
0064     using UnsafeCache = cache::UnsafeCache;
0065     using TestGlobalCache = cache::TestGlobalCache;
0066 
0067     class GlobalIntProducer : public edm::stream::EDProducer<edm::GlobalCache<Cache>> {
0068     public:
0069       static std::atomic<unsigned int> m_count;
0070       unsigned int trans_;
0071       static std::atomic<unsigned int> cvalue_;
0072 
0073       static std::unique_ptr<Cache> initializeGlobalCache(edm::ParameterSet const&) {
0074         ++m_count;
0075         return std::make_unique<Cache>();
0076       }
0077 
0078       GlobalIntProducer(edm::ParameterSet const& p, const Cache* iGlobal) {
0079         trans_ = p.getParameter<int>("transitions");
0080         cvalue_ = p.getParameter<int>("cachevalue");
0081         produces<unsigned int>();
0082       }
0083 
0084       static void globalBeginJob(Cache* iGlobal) {
0085         ++m_count;
0086         if (iGlobal->value != 0) {
0087           throw cms::Exception("cache value") << iGlobal->value << " but it was supposed to be 0";
0088         }
0089       }
0090 
0091       void produce(edm::Event&, edm::EventSetup const&) override {
0092         ++m_count;
0093         ++((globalCache())->value);
0094       }
0095 
0096       static void globalEndJob(Cache* iGlobal) {
0097         ++m_count;
0098         if (iGlobal->value != cvalue_) {
0099           throw cms::Exception("cache value") << iGlobal->value << " but it was supposed to be " << cvalue_;
0100         }
0101       }
0102 
0103       ~GlobalIntProducer() {
0104         if (m_count != trans_) {
0105           throw cms::Exception("transitions") << m_count << " but it was supposed to be " << trans_;
0106         }
0107       }
0108     };
0109 
0110     class RunIntProducer : public edm::stream::EDProducer<edm::RunCache<Cache>> {
0111     public:
0112       static std::atomic<unsigned int> m_count;
0113       unsigned int trans_;
0114       static std::atomic<unsigned int> cvalue_;
0115       static std::atomic<bool> gbr;
0116       static std::atomic<bool> ger;
0117       bool br;
0118       bool er;
0119 
0120       RunIntProducer(edm::ParameterSet const& p) {
0121         trans_ = p.getParameter<int>("transitions");
0122         cvalue_ = p.getParameter<int>("cachevalue");
0123         produces<unsigned int>();
0124       }
0125 
0126       void produce(edm::Event&, edm::EventSetup const&) override {
0127         ++m_count;
0128         ++(runCache()->value);
0129       }
0130 
0131       static std::shared_ptr<Cache> globalBeginRun(edm::Run const& iRun, edm::EventSetup const&, GlobalCache const*) {
0132         ++m_count;
0133         gbr = true;
0134         ger = false;
0135         auto pCache = std::make_shared<Cache>();
0136         ++(pCache->run);
0137         return pCache;
0138       }
0139 
0140       void beginRun(edm::Run const&, edm::EventSetup const&) override {
0141         br = true;
0142         er = true;
0143         if (!gbr) {
0144           throw cms::Exception("begin out of sequence") << "beginRun seen before globalBeginRun";
0145         }
0146       }
0147 
0148       static void globalEndRun(edm::Run const& iRun, edm::EventSetup const&, RunContext const* iContext) {
0149         ++m_count;
0150         auto pCache = iContext->run();
0151         if (pCache->run != 1) {
0152           throw cms::Exception("end out of sequence") << "globalEndRun seen before globalBeginRun in Run" << iRun.run();
0153         }
0154         ger = true;
0155         gbr = false;
0156         if (iContext->run()->value != cvalue_) {
0157           throw cms::Exception("cache value") << iContext->run()->value << " but it was supposed to be " << cvalue_;
0158         }
0159       }
0160 
0161       void endRun(edm::Run const&, edm::EventSetup const&) override {
0162         er = true;
0163         br = false;
0164         if (ger) {
0165           throw cms::Exception("end out of sequence") << "globalEndRun seen before endRun";
0166         }
0167       }
0168 
0169       ~RunIntProducer() {
0170         if (m_count != trans_) {
0171           throw cms::Exception("transitions") << m_count << " but it was supposed to be " << trans_;
0172         }
0173       }
0174     };
0175 
0176     class LumiIntProducer : public edm::stream::EDProducer<edm::LuminosityBlockCache<Cache>> {
0177     public:
0178       static std::atomic<unsigned int> m_count;
0179       unsigned int trans_;
0180       static std::atomic<unsigned int> cvalue_;
0181       static std::atomic<bool> gbl;
0182       static std::atomic<bool> gel;
0183       static std::atomic<bool> bl;
0184       static std::atomic<bool> el;
0185 
0186       LumiIntProducer(edm::ParameterSet const& p) {
0187         trans_ = p.getParameter<int>("transitions");
0188         cvalue_ = p.getParameter<int>("cachevalue");
0189         produces<unsigned int>();
0190       }
0191 
0192       void produce(edm::Event&, edm::EventSetup const&) override {
0193         ++m_count;
0194         ++(luminosityBlockCache()->value);
0195       }
0196 
0197       static std::shared_ptr<Cache> globalBeginLuminosityBlock(edm::LuminosityBlock const& iLB,
0198                                                                edm::EventSetup const&,
0199                                                                RunContext const*) {
0200         ++m_count;
0201         gbl = true;
0202         gel = false;
0203         auto pCache = std::make_shared<Cache>();
0204         ++(pCache->lumi);
0205         return pCache;
0206       }
0207 
0208       void beginLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) override {
0209         bl = true;
0210         el = false;
0211         if (!gbl) {
0212           throw cms::Exception("begin out of sequence")
0213               << "beginLuminosityBlock seen before globalBeginLuminosityBlock";
0214         }
0215       }
0216 
0217       static void globalEndLuminosityBlock(edm::LuminosityBlock const& iLB,
0218                                            edm::EventSetup const&,
0219                                            LuminosityBlockContext const* iLBContext) {
0220         ++m_count;
0221         auto pCache = iLBContext->luminosityBlock();
0222         if (pCache->lumi != 1) {
0223           throw cms::Exception("end out of sequence")
0224               << "globalEndLuminosityBlock seen before globalBeginLuminosityBlock in LuminosityBlock"
0225               << iLB.luminosityBlock();
0226         }
0227         gel = true;
0228         gbl = false;
0229         if (iLBContext->luminosityBlock()->value != cvalue_) {
0230           throw cms::Exception("cache value")
0231               << iLBContext->luminosityBlock()->value << " but it was supposed to be " << cvalue_;
0232         }
0233       }
0234 
0235       static void endLuminosityBlock(edm::Run const&, edm::EventSetup const&, LuminosityBlockContext const*) {
0236         el = true;
0237         bl = false;
0238         if (gel) {
0239           throw cms::Exception("end out of sequence") << "globalEndLuminosityBlock seen before endLuminosityBlock";
0240         }
0241       }
0242 
0243       ~LumiIntProducer() {
0244         if (m_count != trans_) {
0245           throw cms::Exception("transitions") << m_count << " but it was supposed to be " << trans_;
0246         }
0247       }
0248     };
0249 
0250     class RunSummaryIntProducer
0251         : public edm::stream::EDProducer<edm::RunCache<Cache>, edm::RunSummaryCache<UnsafeCache>> {
0252     public:
0253       static std::atomic<unsigned int> m_count;
0254       unsigned int trans_;
0255       static std::atomic<unsigned int> cvalue_;
0256       static std::atomic<bool> gbr;
0257       static std::atomic<bool> ger;
0258       static std::atomic<bool> gbrs;
0259       static std::atomic<bool> gers;
0260       static std::atomic<bool> brs;
0261       static std::atomic<bool> ers;
0262       static std::atomic<bool> br;
0263       static std::atomic<bool> er;
0264 
0265       RunSummaryIntProducer(edm::ParameterSet const& p) {
0266         trans_ = p.getParameter<int>("transitions");
0267         cvalue_ = p.getParameter<int>("cachevalue");
0268         produces<unsigned int>();
0269       }
0270 
0271       void beginRun(edm::Run const&, edm::EventSetup const&) override {
0272         br = true;
0273         er = false;
0274       }
0275 
0276       void produce(edm::Event&, edm::EventSetup const&) override {
0277         ++m_count;
0278         ++(runCache()->value);
0279       }
0280 
0281       static std::shared_ptr<Cache> globalBeginRun(edm::Run const& iRun, edm::EventSetup const&, GlobalCache const*) {
0282         ++m_count;
0283         gbr = true;
0284         ger = false;
0285         auto pCache = std::make_shared<Cache>();
0286         ++(pCache->run);
0287         return pCache;
0288       }
0289 
0290       static std::shared_ptr<UnsafeCache> globalBeginRunSummary(edm::Run const&,
0291                                                                 edm::EventSetup const&,
0292                                                                 GlobalCache const*) {
0293         ++m_count;
0294         gbrs = true;
0295         gers = false;
0296         brs = true;
0297         ers = false;
0298         if (!gbr) {
0299           throw cms::Exception("begin out of sequence") << "globalBeginRunSummary seen before globalBeginRun";
0300         }
0301         return std::make_shared<UnsafeCache>();
0302       }
0303 
0304       void endRunSummary(edm::Run const&, edm::EventSetup const&, UnsafeCache* gCache) const override {
0305         brs = false;
0306         ers = true;
0307         gCache->value += runCache()->value;
0308         runCache()->value = 0;
0309         if (!er) {
0310           throw cms::Exception("end out of sequence") << "endRunSummary seen before endRun";
0311         }
0312       }
0313 
0314       static void globalEndRunSummary(edm::Run const&, edm::EventSetup const&, RunContext const*, UnsafeCache* gCache) {
0315         ++m_count;
0316         gbrs = false;
0317         gers = true;
0318         if (!ers) {
0319           throw cms::Exception("end out of sequence") << "globalEndRunSummary seen before endRunSummary";
0320         }
0321         if (gCache->value != cvalue_) {
0322           throw cms::Exception("cache value") << gCache->value << " but it was supposed to be " << cvalue_;
0323         }
0324       }
0325 
0326       static void globalEndRun(edm::Run const& iRun, edm::EventSetup const&, RunContext const* iContext) {
0327         ++m_count;
0328         gbr = false;
0329         ger = true;
0330         auto pCache = iContext->run();
0331         if (pCache->run != 1) {
0332           throw cms::Exception("end out of sequence") << "globalEndRun seen before globalBeginRun in Run" << iRun.run();
0333         }
0334       }
0335 
0336       void endRun(edm::Run const&, edm::EventSetup const&) override {
0337         er = true;
0338         br = false;
0339       }
0340 
0341       ~RunSummaryIntProducer() {
0342         if (m_count != trans_) {
0343           throw cms::Exception("transitions") << m_count << " but it was supposed to be " << trans_;
0344         }
0345       }
0346     };
0347 
0348     class LumiSummaryIntProducer : public edm::stream::EDProducer<edm::LuminosityBlockCache<Cache>,
0349                                                                   edm::LuminosityBlockSummaryCache<UnsafeCache>> {
0350     public:
0351       static std::atomic<unsigned int> m_count;
0352       static std::atomic<unsigned int> m_lumiSumCalls;
0353       unsigned int trans_;
0354       static std::atomic<unsigned int> cvalue_;
0355       static std::atomic<bool> gbl;
0356       static std::atomic<bool> gel;
0357       static std::atomic<bool> gbls;
0358       static std::atomic<bool> gels;
0359       static std::atomic<bool> bls;
0360       static std::atomic<bool> els;
0361       static std::atomic<bool> bl;
0362       static std::atomic<bool> el;
0363 
0364       LumiSummaryIntProducer(edm::ParameterSet const& p) {
0365         trans_ = p.getParameter<int>("transitions");
0366         cvalue_ = p.getParameter<int>("cachevalue");
0367         produces<unsigned int>();
0368       }
0369 
0370       void produce(edm::Event&, edm::EventSetup const&) override {
0371         ++m_count;
0372         ++(luminosityBlockCache()->value);
0373       }
0374 
0375       void beginLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) override {
0376         bl = true;
0377         el = false;
0378       }
0379 
0380       static std::shared_ptr<Cache> globalBeginLuminosityBlock(edm::LuminosityBlock const& iLB,
0381                                                                edm::EventSetup const&,
0382                                                                RunContext const*) {
0383         ++m_count;
0384         gbl = true;
0385         gel = false;
0386         auto pCache = std::make_shared<Cache>();
0387         ++(pCache->lumi);
0388         return pCache;
0389       }
0390 
0391       static std::shared_ptr<UnsafeCache> globalBeginLuminosityBlockSummary(edm::LuminosityBlock const&,
0392                                                                             edm::EventSetup const&,
0393                                                                             LuminosityBlockContext const*) {
0394         ++m_count;
0395         gbls = true;
0396         gels = false;
0397         bls = true;
0398         els = false;
0399         if (!gbl) {
0400           throw cms::Exception("begin out of sequence")
0401               << "globalBeginLuminosityBlockSummary seen before globalBeginLuminosityBlock";
0402         }
0403         return std::make_shared<UnsafeCache>();
0404       }
0405 
0406       void endLuminosityBlockSummary(edm::LuminosityBlock const&,
0407                                      edm::EventSetup const&,
0408                                      UnsafeCache* gCache) const override {
0409         ++m_lumiSumCalls;
0410         bls = false;
0411         els = true;
0412         //This routine could be called at the same time as another stream is calling produce so must do the change atomically
0413         auto v = luminosityBlockCache()->value.exchange(0);
0414         gCache->value += v;
0415         if (el) {
0416           throw cms::Exception("end out of sequence") << "endLuminosityBlock seen before endLuminosityBlockSummary";
0417         }
0418       }
0419 
0420       static void globalEndLuminosityBlockSummary(edm::LuminosityBlock const&,
0421                                                   edm::EventSetup const&,
0422                                                   LuminosityBlockContext const*,
0423                                                   UnsafeCache* gCache) {
0424         ++m_count;
0425         auto nLumis = m_lumiSumCalls.load();
0426         gbls = false;
0427         gels = true;
0428         if (!els) {
0429           throw cms::Exception("end out of sequence")
0430               << "globalEndLuminosityBlockSummary seen before endLuminosityBlockSummary";
0431         }
0432         if (gCache->value != cvalue_) {
0433           throw cms::Exception("cache value")
0434               << gCache->value << " but it was supposed to be " << cvalue_ << " endLumiBlockSummary called " << nLumis;
0435         }
0436       }
0437 
0438       static void globalEndLuminosityBlock(edm::LuminosityBlock const& iLB,
0439                                            edm::EventSetup const&,
0440                                            LuminosityBlockContext const* iLBContext) {
0441         ++m_count;
0442         auto pCache = iLBContext->luminosityBlock();
0443         if (pCache->lumi != 1) {
0444           throw cms::Exception("end out of sequence")
0445               << "globalEndLuminosityBlock seen before globalBeginLuminosityBlock in LuminosityBlock"
0446               << iLB.luminosityBlock();
0447         }
0448         gel = true;
0449         gbl = false;
0450         if (!gels) {
0451           throw cms::Exception("end out of sequence")
0452               << "globalEndLuminosityBlockSummary seen before globalEndLuminosityBlock";
0453         }
0454       }
0455 
0456       static void endLuminosityBlock(edm::Run const&, edm::EventSetup const&, LuminosityBlockContext const*) {
0457         el = true;
0458         bl = false;
0459       }
0460 
0461       ~LumiSummaryIntProducer() {
0462         if (m_count != trans_) {
0463           throw cms::Exception("transitions") << m_count << " but it was supposed to be " << trans_;
0464         }
0465       }
0466     };
0467 
0468     class ProcessBlockIntProducer
0469         : public edm::stream::EDProducer<edm::WatchProcessBlock, edm::GlobalCache<TestGlobalCache>> {
0470     public:
0471       explicit ProcessBlockIntProducer(edm::ParameterSet const& pset, TestGlobalCache const* testGlobalCache) {
0472         {
0473           auto tag = pset.getParameter<edm::InputTag>("consumesBeginProcessBlock");
0474           if (not tag.label().empty()) {
0475             testGlobalCache->getTokenBegin_ = consumes<unsigned int, edm::InProcess>(tag);
0476           }
0477         }
0478         {
0479           auto tag = pset.getParameter<edm::InputTag>("consumesEndProcessBlock");
0480           if (not tag.label().empty()) {
0481             testGlobalCache->getTokenEnd_ = consumes<unsigned int, edm::InProcess>(tag);
0482           }
0483         }
0484       }
0485 
0486       static std::unique_ptr<TestGlobalCache> initializeGlobalCache(edm::ParameterSet const& pset) {
0487         auto testGlobalCache = std::make_unique<TestGlobalCache>();
0488         testGlobalCache->trans_ = pset.getParameter<int>("transitions");
0489         return testGlobalCache;
0490       }
0491 
0492       static void beginProcessBlock(edm::ProcessBlock const& processBlock, TestGlobalCache* testGlobalCache) {
0493         if (testGlobalCache->m_count != 0) {
0494           throw cms::Exception("transitions") << "ProcessBlockIntProducer::begin transitions "
0495                                               << testGlobalCache->m_count << " but it was supposed to be " << 0;
0496         }
0497         ++testGlobalCache->m_count;
0498 
0499         const unsigned int valueToGet = 51;
0500         if (not testGlobalCache->getTokenBegin_.isUninitialized()) {
0501           if (processBlock.get(testGlobalCache->getTokenBegin_) != valueToGet) {
0502             throw cms::Exception("BadValue")
0503                 << "expected " << valueToGet << " but got " << processBlock.get(testGlobalCache->getTokenBegin_);
0504           }
0505         }
0506       }
0507 
0508       void produce(edm::Event&, edm::EventSetup const&) override {
0509         TestGlobalCache const* testGlobalCache = globalCache();
0510         if (testGlobalCache->m_count < 1u) {
0511           throw cms::Exception("out of sequence") << "produce before beginProcessBlock " << testGlobalCache->m_count;
0512         }
0513         ++testGlobalCache->m_count;
0514       }
0515 
0516       static void endProcessBlock(edm::ProcessBlock const& processBlock, TestGlobalCache* testGlobalCache) {
0517         ++testGlobalCache->m_count;
0518         if (testGlobalCache->m_count != testGlobalCache->trans_) {
0519           throw cms::Exception("transitions") << "ProcessBlockIntProducer::end transitions " << testGlobalCache->m_count
0520                                               << " but it was supposed to be " << testGlobalCache->trans_;
0521         }
0522         {
0523           const unsigned int valueToGet = 51;
0524           if (not testGlobalCache->getTokenBegin_.isUninitialized()) {
0525             if (processBlock.get(testGlobalCache->getTokenBegin_) != valueToGet) {
0526               throw cms::Exception("BadValue")
0527                   << "expected " << valueToGet << " but got " << processBlock.get(testGlobalCache->getTokenBegin_);
0528             }
0529           }
0530         }
0531         {
0532           const unsigned int valueToGet = 61;
0533           if (not testGlobalCache->getTokenEnd_.isUninitialized()) {
0534             if (processBlock.get(testGlobalCache->getTokenEnd_) != valueToGet) {
0535               throw cms::Exception("BadValue")
0536                   << "expected " << valueToGet << " but got " << processBlock.get(testGlobalCache->getTokenEnd_);
0537             }
0538           }
0539         }
0540       }
0541 
0542       static void globalEndJob(TestGlobalCache* testGlobalCache) {
0543         if (testGlobalCache->m_count != testGlobalCache->trans_) {
0544           throw cms::Exception("transitions")
0545               << "TestBeginProcessBlockProducer transitions " << testGlobalCache->m_count
0546               << " but it was supposed to be " << testGlobalCache->trans_;
0547         }
0548       }
0549 
0550       ~ProcessBlockIntProducer() {
0551         TestGlobalCache const* testGlobalCache = globalCache();
0552         if (testGlobalCache->m_count != testGlobalCache->trans_) {
0553           throw cms::Exception("transitions") << "ProcessBlockIntProducer transitions " << testGlobalCache->m_count
0554                                               << " but it was supposed to be " << testGlobalCache->trans_;
0555         }
0556       }
0557     };
0558 
0559     class TestBeginProcessBlockProducer
0560         : public edm::stream::EDProducer<edm::BeginProcessBlockProducer, edm::GlobalCache<TestGlobalCache>> {
0561     public:
0562       explicit TestBeginProcessBlockProducer(edm::ParameterSet const& pset, TestGlobalCache const* testGlobalCache) {
0563         testGlobalCache->token_ = produces<unsigned int, edm::Transition::BeginProcessBlock>("begin");
0564 
0565         auto tag = pset.getParameter<edm::InputTag>("consumesBeginProcessBlock");
0566         if (not tag.label().empty()) {
0567           testGlobalCache->getTokenBegin_ = consumes<unsigned int, edm::InProcess>(tag);
0568         }
0569       }
0570 
0571       static std::unique_ptr<TestGlobalCache> initializeGlobalCache(edm::ParameterSet const& pset) {
0572         auto testGlobalCache = std::make_unique<TestGlobalCache>();
0573         testGlobalCache->trans_ = pset.getParameter<int>("transitions");
0574         return testGlobalCache;
0575       }
0576 
0577       static void beginProcessBlockProduce(edm::ProcessBlock& processBlock, TestGlobalCache const* testGlobalCache) {
0578         if (testGlobalCache->m_count != 0) {
0579           throw cms::Exception("transitions") << "TestBeginProcessBlockProducer transitions "
0580                                               << testGlobalCache->m_count << " but it was supposed to be " << 0;
0581         }
0582         ++testGlobalCache->m_count;
0583 
0584         const unsigned int valueToPutAndGet = 51;
0585         processBlock.emplace(testGlobalCache->token_, valueToPutAndGet);
0586 
0587         if (not testGlobalCache->getTokenBegin_.isUninitialized()) {
0588           if (processBlock.get(testGlobalCache->getTokenBegin_) != valueToPutAndGet) {
0589             throw cms::Exception("BadValue")
0590                 << "expected " << valueToPutAndGet << " but got " << processBlock.get(testGlobalCache->getTokenBegin_);
0591           }
0592         }
0593       }
0594 
0595       void produce(edm::Event&, edm::EventSetup const&) override {
0596         TestGlobalCache const* testGlobalCache = globalCache();
0597         if (testGlobalCache->m_count < 1u) {
0598           throw cms::Exception("out of sequence")
0599               << "produce before beginProcessBlockProduce " << testGlobalCache->m_count;
0600         }
0601         ++testGlobalCache->m_count;
0602       }
0603 
0604       static void globalEndJob(TestGlobalCache* testGlobalCache) {
0605         if (testGlobalCache->m_count != testGlobalCache->trans_) {
0606           throw cms::Exception("transitions")
0607               << "TestBeginProcessBlockProducer transitions " << testGlobalCache->m_count
0608               << " but it was supposed to be " << testGlobalCache->trans_;
0609         }
0610       }
0611 
0612       ~TestBeginProcessBlockProducer() {
0613         TestGlobalCache const* testGlobalCache = globalCache();
0614         if (testGlobalCache->m_count != testGlobalCache->trans_) {
0615           throw cms::Exception("transitions")
0616               << "TestBeginProcessBlockProducer transitions " << testGlobalCache->m_count
0617               << " but it was supposed to be " << testGlobalCache->trans_;
0618         }
0619       }
0620     };
0621 
0622     class TestEndProcessBlockProducer
0623         : public edm::stream::EDProducer<edm::EndProcessBlockProducer, edm::GlobalCache<TestGlobalCache>> {
0624     public:
0625       explicit TestEndProcessBlockProducer(edm::ParameterSet const& pset, TestGlobalCache const* testGlobalCache) {
0626         testGlobalCache->token_ = produces<unsigned int, edm::Transition::EndProcessBlock>("end");
0627 
0628         auto tag = pset.getParameter<edm::InputTag>("consumesEndProcessBlock");
0629         if (not tag.label().empty()) {
0630           testGlobalCache->getTokenEnd_ = consumes<unsigned int, edm::InProcess>(tag);
0631         }
0632       }
0633 
0634       static std::unique_ptr<TestGlobalCache> initializeGlobalCache(edm::ParameterSet const& pset) {
0635         auto testGlobalCache = std::make_unique<TestGlobalCache>();
0636         testGlobalCache->trans_ = pset.getParameter<int>("transitions");
0637         return testGlobalCache;
0638       }
0639 
0640       void produce(edm::Event&, edm::EventSetup const&) override {
0641         TestGlobalCache const* testGlobalCache = globalCache();
0642         ++testGlobalCache->m_count;
0643       }
0644 
0645       static void endProcessBlockProduce(edm::ProcessBlock& processBlock, TestGlobalCache const* testGlobalCache) {
0646         ++testGlobalCache->m_count;
0647         if (testGlobalCache->m_count != testGlobalCache->trans_) {
0648           throw cms::Exception("transitions") << "TestEndProcessBlockProducer transitions " << testGlobalCache->m_count
0649                                               << " but it was supposed to be " << testGlobalCache->trans_;
0650         }
0651         const unsigned int valueToPutAndGet = 61;
0652         processBlock.emplace(testGlobalCache->token_, valueToPutAndGet);
0653 
0654         if (not testGlobalCache->getTokenEnd_.isUninitialized()) {
0655           if (processBlock.get(testGlobalCache->getTokenEnd_) != valueToPutAndGet) {
0656             throw cms::Exception("BadValue")
0657                 << "expected " << valueToPutAndGet << " but got " << processBlock.get(testGlobalCache->getTokenEnd_);
0658           }
0659         }
0660       }
0661 
0662       static void globalEndJob(TestGlobalCache* testGlobalCache) {
0663         if (testGlobalCache->m_count != testGlobalCache->trans_) {
0664           throw cms::Exception("transitions")
0665               << "TestBeginProcessBlockProducer transitions " << testGlobalCache->m_count
0666               << " but it was supposed to be " << testGlobalCache->trans_;
0667         }
0668       }
0669 
0670       ~TestEndProcessBlockProducer() {
0671         TestGlobalCache const* testGlobalCache = globalCache();
0672         if (testGlobalCache->m_count != testGlobalCache->trans_) {
0673           throw cms::Exception("transitions") << "~TestEndProcessBlockProducer transitions " << testGlobalCache->m_count
0674                                               << " but it was supposed to be " << testGlobalCache->trans_;
0675         }
0676       }
0677     };
0678 
0679     class ProcessBlockIntProducerNoGlobalCache : public edm::stream::EDProducer<edm::WatchProcessBlock> {
0680     public:
0681       explicit ProcessBlockIntProducerNoGlobalCache(edm::ParameterSet const&) {}
0682 
0683       static void beginProcessBlock(edm::ProcessBlock const&) {}
0684 
0685       void produce(edm::Event&, edm::EventSetup const&) override {}
0686 
0687       static void endProcessBlock(edm::ProcessBlock const&) {}
0688     };
0689 
0690     class TestBeginProcessBlockProducerNoGlobalCache : public edm::stream::EDProducer<edm::BeginProcessBlockProducer> {
0691     public:
0692       explicit TestBeginProcessBlockProducerNoGlobalCache(edm::ParameterSet const&) {}
0693 
0694       static void beginProcessBlockProduce(edm::ProcessBlock&) {}
0695 
0696       void produce(edm::Event&, edm::EventSetup const&) override {}
0697     };
0698 
0699     class TestEndProcessBlockProducerNoGlobalCache : public edm::stream::EDProducer<edm::EndProcessBlockProducer> {
0700     public:
0701       explicit TestEndProcessBlockProducerNoGlobalCache(edm::ParameterSet const&) {}
0702 
0703       void produce(edm::Event&, edm::EventSetup const&) override {}
0704 
0705       static void endProcessBlockProduce(edm::ProcessBlock&) {}
0706     };
0707 
0708     class TestBeginRunProducer : public edm::stream::EDProducer<edm::RunCache<bool>, edm::BeginRunProducer> {
0709     public:
0710       static std::atomic<unsigned int> m_count;
0711       unsigned int trans_;
0712       static std::atomic<unsigned int> cvalue_;
0713       static std::atomic<bool> gbr;
0714       static std::atomic<bool> ger;
0715       static std::atomic<bool> gbrp;
0716 
0717       TestBeginRunProducer(edm::ParameterSet const& p) {
0718         trans_ = p.getParameter<int>("transitions");
0719         cvalue_ = p.getParameter<int>("cachevalue");
0720         produces<unsigned int>();
0721         produces<unsigned int, edm::Transition::BeginRun>("a");
0722       }
0723 
0724       static std::shared_ptr<bool> globalBeginRun(edm::Run const& iRun, edm::EventSetup const&, GlobalCache const*) {
0725         gbr = true;
0726         ger = false;
0727         gbrp = false;
0728         return std::shared_ptr<bool>{};
0729       }
0730 
0731       void produce(edm::Event&, edm::EventSetup const&) override {
0732         if (!gbrp) {
0733           throw cms::Exception("out of sequence") << "produce before globalBeginRunProduce";
0734         }
0735       }
0736 
0737       static void globalBeginRunProduce(edm::Run& iRun, edm::EventSetup const&, RunContext const*) {
0738         gbrp = true;
0739         ++m_count;
0740         if (!gbr) {
0741           throw cms::Exception("begin out of sequence") << "globalBeginRunProduce seen before globalBeginRun";
0742         }
0743       }
0744 
0745       static void globalEndRun(edm::Run const& iRun, edm::EventSetup const&, RunContext const* iContext) {
0746         if (!gbr) {
0747           throw cms::Exception("end out of sequence") << "globalEndRun seen before globalBeginRun in Run" << iRun.run();
0748         }
0749         gbr = false;
0750         ger = true;
0751       }
0752 
0753       ~TestBeginRunProducer() {
0754         if (m_count != trans_) {
0755           throw cms::Exception("transitions") << m_count << " but it was supposed to be " << trans_;
0756         }
0757       }
0758     };
0759 
0760     class TestEndRunProducer : public edm::stream::EDProducer<edm::RunCache<bool>, edm::EndRunProducer> {
0761     public:
0762       static std::atomic<unsigned int> m_count;
0763       unsigned int trans_;
0764       static std::atomic<unsigned int> cvalue_;
0765       static std::atomic<bool> gbr;
0766       static std::atomic<bool> ger;
0767       static std::atomic<bool> p;
0768 
0769       static std::shared_ptr<bool> globalBeginRun(edm::Run const& iRun, edm::EventSetup const&, GlobalCache const*) {
0770         gbr = true;
0771         ger = false;
0772         p = false;
0773         return std::shared_ptr<bool>{};
0774       }
0775 
0776       TestEndRunProducer(edm::ParameterSet const& p) {
0777         trans_ = p.getParameter<int>("transitions");
0778         cvalue_ = p.getParameter<int>("cachevalue");
0779         produces<unsigned int>();
0780         produces<unsigned int, edm::Transition::EndRun>("a");
0781       }
0782 
0783       void produce(edm::Event&, edm::EventSetup const&) override { p = true; }
0784 
0785       static void globalEndRunProduce(edm::Run& iRun, edm::EventSetup const&, RunContext const*) {
0786         ++m_count;
0787         if (!p) {
0788           throw cms::Exception("out of sequence") << "globalEndRunProduce seen before produce";
0789         }
0790         if (ger) {
0791           throw cms::Exception("out of sequence") << "globalEndRun seen before globalEndRunProduce";
0792         }
0793       }
0794 
0795       static void globalEndRun(edm::Run const& iRun, edm::EventSetup const&, RunContext const* iContext) {
0796         if (!gbr) {
0797           throw cms::Exception("out of sequence") << "globalEndRun seen before globalBeginRun in Run" << iRun.run();
0798         }
0799         gbr = false;
0800         ger = true;
0801       }
0802 
0803       ~TestEndRunProducer() {
0804         if (m_count != trans_) {
0805           throw cms::Exception("transitions") << m_count << " but it was supposed to be " << trans_;
0806         }
0807       }
0808     };
0809 
0810     class TestBeginLumiBlockProducer
0811         : public edm::stream::EDProducer<edm::LuminosityBlockCache<bool>, edm::BeginLuminosityBlockProducer> {
0812     public:
0813       static std::atomic<unsigned int> m_count;
0814       unsigned int trans_;
0815       static std::atomic<unsigned int> cvalue_;
0816       static std::atomic<bool> gbl;
0817       static std::atomic<bool> gel;
0818       static std::atomic<bool> gblp;
0819 
0820       TestBeginLumiBlockProducer(edm::ParameterSet const& p) {
0821         trans_ = p.getParameter<int>("transitions");
0822         cvalue_ = p.getParameter<int>("cachevalue");
0823         produces<unsigned int>();
0824         produces<unsigned int, edm::Transition::BeginLuminosityBlock>("a");
0825       }
0826 
0827       void produce(edm::Event&, edm::EventSetup const&) override {
0828         if (!gblp) {
0829           throw cms::Exception("begin out of sequence") << "produce seen before globalBeginLumiBlockProduce";
0830         }
0831       }
0832 
0833       static void globalBeginLuminosityBlockProduce(edm::LuminosityBlock&,
0834                                                     edm::EventSetup const&,
0835                                                     LuminosityBlockContext const*) {
0836         ++m_count;
0837         if (!gbl) {
0838           throw cms::Exception("begin out of sequence")
0839               << "globalBeginLumiBlockProduce seen before globalBeginLumiBlock";
0840         }
0841         gblp = true;
0842       }
0843 
0844       static std::shared_ptr<bool> globalBeginLuminosityBlock(edm::LuminosityBlock const& iLB,
0845                                                               edm::EventSetup const&,
0846                                                               RunContext const*) {
0847         gbl = true;
0848         gel = false;
0849         gblp = false;
0850         return std::shared_ptr<bool>();
0851       }
0852 
0853       static void globalEndLuminosityBlock(edm::LuminosityBlock const& iLB,
0854                                            edm::EventSetup const&,
0855                                            LuminosityBlockContext const* iLBContext) {
0856         if (!gbl) {
0857           throw cms::Exception("end out of sequence")
0858               << "globalEndLuminosityBlock seen before globalBeginLuminosityBlock in LuminosityBlock"
0859               << iLB.luminosityBlock();
0860         }
0861         gel = true;
0862         gbl = false;
0863       }
0864 
0865       ~TestBeginLumiBlockProducer() {
0866         if (m_count != trans_) {
0867           throw cms::Exception("transitions") << m_count << " but it was supposed to be " << trans_;
0868         }
0869       }
0870     };
0871 
0872     class TestEndLumiBlockProducer
0873         : public edm::stream::EDProducer<edm::LuminosityBlockCache<bool>, edm::EndLuminosityBlockProducer> {
0874     public:
0875       static std::atomic<unsigned int> m_count;
0876       unsigned int trans_;
0877       static std::atomic<unsigned int> cvalue_;
0878       static std::atomic<bool> gbl;
0879       static std::atomic<bool> gel;
0880       static std::atomic<bool> p;
0881 
0882       TestEndLumiBlockProducer(edm::ParameterSet const& p) {
0883         trans_ = p.getParameter<int>("transitions");
0884         cvalue_ = p.getParameter<int>("cachevalue");
0885         produces<unsigned int>();
0886         produces<unsigned int, edm::Transition::EndLuminosityBlock>("a");
0887       }
0888 
0889       void produce(edm::Event&, edm::EventSetup const&) override { p = true; }
0890 
0891       static void globalEndLuminosityBlockProduce(edm::LuminosityBlock&,
0892                                                   edm::EventSetup const&,
0893                                                   LuminosityBlockContext const*) {
0894         ++m_count;
0895         if (!p) {
0896           throw cms::Exception("out of sequence") << "globalEndLumiBlockProduce seen before produce";
0897         }
0898       }
0899 
0900       static std::shared_ptr<bool> globalBeginLuminosityBlock(edm::LuminosityBlock const& iLB,
0901                                                               edm::EventSetup const&,
0902                                                               RunContext const*) {
0903         gbl = true;
0904         gel = false;
0905         p = false;
0906         return std::shared_ptr<bool>{};
0907       }
0908 
0909       static void globalEndLuminosityBlock(edm::LuminosityBlock const& iLB,
0910                                            edm::EventSetup const&,
0911                                            LuminosityBlockContext const* iLBContext) {
0912         if (!gbl) {
0913           throw cms::Exception("end out of sequence")
0914               << "globalEndLuminosityBlock seen before globalBeginLuminosityBlock in LuminosityBlock"
0915               << iLB.luminosityBlock();
0916         }
0917       }
0918 
0919       ~TestEndLumiBlockProducer() {
0920         if (m_count != trans_) {
0921           throw cms::Exception("transitions") << m_count << " but it was supposed to be " << trans_;
0922         }
0923       }
0924     };
0925 
0926     struct Count {
0927       Count() : m_value(0), m_expectedValue(0) {}
0928       //Using mutable since we want to update the value.
0929       mutable std::atomic<unsigned int> m_value;
0930       mutable std::atomic<unsigned int> m_expectedValue;
0931       // Set only in constructor, framework runs constructors serially
0932       CMS_THREAD_SAFE mutable edm::EDPutTokenT<unsigned int> m_putToken;
0933     };
0934 
0935     class TestAccumulator
0936         : public edm::stream::EDProducer<edm::GlobalCache<Count>, edm::Accumulator, edm::EndLuminosityBlockProducer> {
0937     public:
0938       static std::atomic<unsigned int> m_expectedCount;
0939 
0940       explicit TestAccumulator(edm::ParameterSet const& p, Count const* iCount) {
0941         iCount->m_expectedValue = p.getParameter<unsigned int>("expectedCount");
0942         if (iCount->m_putToken.isUninitialized()) {
0943           iCount->m_putToken = produces<unsigned int, edm::Transition::EndLuminosityBlock>();
0944         }
0945       }
0946 
0947       static std::unique_ptr<Count> initializeGlobalCache(edm::ParameterSet const&) {
0948         return std::unique_ptr<Count>(new Count());
0949       }
0950 
0951       void accumulate(edm::Event const&, edm::EventSetup const&) override { ++(globalCache()->m_value); }
0952 
0953       static void globalEndLuminosityBlockProduce(edm::LuminosityBlock& l,
0954                                                   edm::EventSetup const&,
0955                                                   LuminosityBlockContext const* ctx) {
0956         Count const* count = ctx->global();
0957         l.emplace(count->m_putToken, count->m_value.load());
0958       }
0959 
0960       static void globalEndJob(Count const* iCount) {
0961         if (iCount->m_value != iCount->m_expectedValue) {
0962           throw cms::Exception("CountEvents") << "Number of events seen = " << iCount->m_value
0963                                               << " but it was supposed to be " << iCount->m_expectedValue;
0964         }
0965       }
0966 
0967       ~TestAccumulator() {}
0968     };
0969 
0970     class TestInputProcessBlockCache {
0971     public:
0972       long long int value_ = 0;
0973     };
0974 
0975     class TestInputProcessBlockCache1 {
0976     public:
0977       long long int value_ = 0;
0978     };
0979 
0980     class InputProcessBlockIntProducer
0981         : public edm::stream::EDProducer<
0982               edm::InputProcessBlockCache<int, TestInputProcessBlockCache, TestInputProcessBlockCache1>> {
0983     public:
0984       explicit InputProcessBlockIntProducer(edm::ParameterSet const& pset) {
0985         {
0986           expectedByRun_ = pset.getParameter<std::vector<int>>("expectedByRun");
0987           sleepTime_ = pset.getParameter<unsigned int>("sleepTime");
0988           auto tag = pset.getParameter<edm::InputTag>("consumesBeginProcessBlock");
0989           if (not tag.label().empty()) {
0990             getTokenBegin_ = consumes<IntProduct, edm::InProcess>(tag);
0991           }
0992         }
0993         {
0994           auto tag = pset.getParameter<edm::InputTag>("consumesEndProcessBlock");
0995           if (not tag.label().empty()) {
0996             getTokenEnd_ = consumes<IntProduct, edm::InProcess>(tag);
0997           }
0998         }
0999         registerProcessBlockCacheFiller<TestInputProcessBlockCache1>(
1000             getTokenBegin_,
1001             [this](edm::ProcessBlock const& processBlock,
1002                    std::shared_ptr<TestInputProcessBlockCache1> const& previousCache) {
1003               auto returnValue = std::make_shared<TestInputProcessBlockCache1>();
1004               returnValue->value_ += processBlock.get(getTokenBegin_).value;
1005               returnValue->value_ += processBlock.get(getTokenEnd_).value;
1006               return returnValue;
1007             });
1008       }
1009 
1010       static void accessInputProcessBlock(edm::ProcessBlock const&) {
1011         edm::LogAbsolute("InputProcessBlockIntProducer") << "InputProcessBlockIntProducer::accessInputProcessBlock";
1012       }
1013 
1014       void produce(edm::Event& event, edm::EventSetup const&) override {
1015         auto cacheTuple = processBlockCaches(event);
1016         if (!expectedByRun_.empty()) {
1017           if (expectedByRun_.at(event.run() - 1) !=
1018               std::get<edm::CacheHandle<TestInputProcessBlockCache1>>(cacheTuple)->value_) {
1019             throw cms::Exception("UnexpectedValue")
1020                 << "InputProcessBlockIntProducer::produce cached value was "
1021                 << std::get<edm::CacheHandle<TestInputProcessBlockCache1>>(cacheTuple)->value_
1022                 << " but it was supposed to be " << expectedByRun_.at(event.run() - 1);
1023           }
1024         }
1025         // Force events to be processed concurrently
1026         if (sleepTime_ > 0) {
1027           usleep(sleepTime_);
1028         }
1029       }
1030 
1031     private:
1032       edm::EDGetTokenT<IntProduct> getTokenBegin_;
1033       edm::EDGetTokenT<IntProduct> getTokenEnd_;
1034       std::vector<int> expectedByRun_;
1035       unsigned int sleepTime_{0};
1036     };
1037 
1038     struct InputProcessBlockGlobalCacheAn {
1039       // The tokens are duplicated in this test module to prove that they
1040       // work both as GlobalCache members and module data members.
1041       // We need them as GlobalCache members for accessInputProcessBlock.
1042       // In registerProcessBlockCacheFiller we use tokens that are member
1043       // variables of the class and because the lambda captures the "this"
1044       // pointer of the zeroth stream module instance. We always
1045       // use the zeroth EDConsumer. In the case of registerProcessBlockCacheFiller,
1046       // either set of tokens would work. Note that in the GlobalCache case
1047       // there is a slight weirdness that the zeroth consumer is used but
1048       // the token comes from the last consumer instance. It works because
1049       // all the stream module instances have EDConsumer base classes with
1050       // containers with the same contents in the same order (not 100% guaranteed,
1051       // but it would be difficult to implement a module where this isn't true).
1052       CMS_THREAD_SAFE mutable edm::EDGetTokenT<IntProduct> getTokenBegin_;
1053       CMS_THREAD_SAFE mutable edm::EDGetTokenT<IntProduct> getTokenEnd_;
1054       CMS_THREAD_SAFE mutable edm::EDGetTokenT<IntProduct> getTokenBeginM_;
1055       CMS_THREAD_SAFE mutable edm::EDGetTokenT<IntProduct> getTokenEndM_;
1056       mutable std::atomic<unsigned int> transitions_{0};
1057       int sum_{0};
1058       unsigned int expectedTransitions_{0};
1059       std::vector<int> expectedByRun_;
1060       int expectedSum_{0};
1061       unsigned int sleepTime_{0};
1062     };
1063 
1064     // Same thing as previous class except with a GlobalCache added
1065     class InputProcessBlockIntProducerG
1066         : public edm::stream::EDProducer<
1067               edm::InputProcessBlockCache<int, TestInputProcessBlockCache, TestInputProcessBlockCache1>,
1068               edm::GlobalCache<InputProcessBlockGlobalCacheAn>> {
1069     public:
1070       explicit InputProcessBlockIntProducerG(edm::ParameterSet const& pset,
1071                                              InputProcessBlockGlobalCacheAn const* testGlobalCache) {
1072         {
1073           auto tag = pset.getParameter<edm::InputTag>("consumesBeginProcessBlock");
1074           if (not tag.label().empty()) {
1075             getTokenBegin_ = consumes<IntProduct, edm::InProcess>(tag);
1076             testGlobalCache->getTokenBegin_ = getTokenBegin_;
1077           }
1078         }
1079         {
1080           auto tag = pset.getParameter<edm::InputTag>("consumesEndProcessBlock");
1081           if (not tag.label().empty()) {
1082             getTokenEnd_ = consumes<IntProduct, edm::InProcess>(tag);
1083             testGlobalCache->getTokenEnd_ = getTokenEnd_;
1084           }
1085         }
1086         {
1087           auto tag = pset.getParameter<edm::InputTag>("consumesBeginProcessBlockM");
1088           if (not tag.label().empty()) {
1089             getTokenBeginM_ = consumes<IntProduct, edm::InProcess>(tag);
1090             testGlobalCache->getTokenBeginM_ = getTokenBeginM_;
1091           }
1092         }
1093         {
1094           auto tag = pset.getParameter<edm::InputTag>("consumesEndProcessBlockM");
1095           if (not tag.label().empty()) {
1096             getTokenEndM_ = consumes<IntProduct, edm::InProcess>(tag);
1097             testGlobalCache->getTokenEndM_ = getTokenEndM_;
1098           }
1099         }
1100         registerProcessBlockCacheFiller<int>(
1101             getTokenBegin_, [this](edm::ProcessBlock const& processBlock, std::shared_ptr<int> const& previousCache) {
1102               auto returnValue = std::make_shared<int>(0);
1103               *returnValue += processBlock.get(getTokenBegin_).value;
1104               *returnValue += processBlock.get(getTokenEnd_).value;
1105               ++globalCache()->transitions_;
1106               return returnValue;
1107             });
1108         registerProcessBlockCacheFiller<1>(getTokenBegin_,
1109                                            [this](edm::ProcessBlock const& processBlock,
1110                                                   std::shared_ptr<TestInputProcessBlockCache> const& previousCache) {
1111                                              auto returnValue = std::make_shared<TestInputProcessBlockCache>();
1112                                              returnValue->value_ += processBlock.get(getTokenBegin_).value;
1113                                              returnValue->value_ += processBlock.get(getTokenEnd_).value;
1114                                              ++globalCache()->transitions_;
1115                                              return returnValue;
1116                                            });
1117         registerProcessBlockCacheFiller<TestInputProcessBlockCache1>(
1118             getTokenBegin_,
1119             [this](edm::ProcessBlock const& processBlock,
1120                    std::shared_ptr<TestInputProcessBlockCache1> const& previousCache) {
1121               auto returnValue = std::make_shared<TestInputProcessBlockCache1>();
1122               returnValue->value_ += processBlock.get(getTokenBegin_).value;
1123               returnValue->value_ += processBlock.get(getTokenEnd_).value;
1124               ++globalCache()->transitions_;
1125               return returnValue;
1126             });
1127       }
1128 
1129       static std::unique_ptr<InputProcessBlockGlobalCacheAn> initializeGlobalCache(edm::ParameterSet const& pset) {
1130         auto testGlobalCache = std::make_unique<InputProcessBlockGlobalCacheAn>();
1131         testGlobalCache->expectedTransitions_ = pset.getParameter<int>("transitions");
1132         testGlobalCache->expectedByRun_ = pset.getParameter<std::vector<int>>("expectedByRun");
1133         testGlobalCache->expectedSum_ = pset.getParameter<int>("expectedSum");
1134         testGlobalCache->sleepTime_ = pset.getParameter<unsigned int>("sleepTime");
1135         return testGlobalCache;
1136       }
1137 
1138       static void accessInputProcessBlock(edm::ProcessBlock const& processBlock,
1139                                           InputProcessBlockGlobalCacheAn* testGlobalCache) {
1140         if (processBlock.processName() == "PROD1") {
1141           testGlobalCache->sum_ += processBlock.get(testGlobalCache->getTokenBegin_).value;
1142           testGlobalCache->sum_ += processBlock.get(testGlobalCache->getTokenEnd_).value;
1143         }
1144         if (processBlock.processName() == "MERGE") {
1145           testGlobalCache->sum_ += processBlock.get(testGlobalCache->getTokenBeginM_).value;
1146           testGlobalCache->sum_ += processBlock.get(testGlobalCache->getTokenEndM_).value;
1147         }
1148         ++testGlobalCache->transitions_;
1149       }
1150 
1151       void produce(edm::Event& event, edm::EventSetup const&) override {
1152         auto cacheTuple = processBlockCaches(event);
1153         auto testGlobalCache = globalCache();
1154         if (!testGlobalCache->expectedByRun_.empty()) {
1155           if (testGlobalCache->expectedByRun_.at(event.run() - 1) != *std::get<edm::CacheHandle<int>>(cacheTuple)) {
1156             throw cms::Exception("UnexpectedValue")
1157                 << "InputProcessBlockIntProducerG::produce cached value was "
1158                 << *std::get<edm::CacheHandle<int>>(cacheTuple) << " but it was supposed to be "
1159                 << testGlobalCache->expectedByRun_.at(event.run() - 1);
1160           }
1161           if (testGlobalCache->expectedByRun_.at(event.run() - 1) != std::get<1>(cacheTuple)->value_) {
1162             throw cms::Exception("UnexpectedValue")
1163                 << "InputProcessBlockIntProducerG::produce second cached value was " << std::get<1>(cacheTuple)->value_
1164                 << " but it was supposed to be " << testGlobalCache->expectedByRun_.at(event.run() - 1);
1165           }
1166           if (testGlobalCache->expectedByRun_.at(event.run() - 1) !=
1167               std::get<edm::CacheHandle<TestInputProcessBlockCache1>>(cacheTuple)->value_) {
1168             throw cms::Exception("UnexpectedValue")
1169                 << "InputProcessBlockIntProducerG::produce third cached value was "
1170                 << std::get<edm::CacheHandle<TestInputProcessBlockCache1>>(cacheTuple)->value_
1171                 << " but it was supposed to be " << testGlobalCache->expectedByRun_.at(event.run() - 1);
1172           }
1173         }
1174         ++testGlobalCache->transitions_;
1175 
1176         // Force events to be processed concurrently
1177         if (testGlobalCache->sleepTime_ > 0) {
1178           usleep(testGlobalCache->sleepTime_);
1179         }
1180       }
1181 
1182       static void globalEndJob(InputProcessBlockGlobalCacheAn* testGlobalCache) {
1183         if (testGlobalCache->transitions_ != testGlobalCache->expectedTransitions_) {
1184           throw cms::Exception("transitions")
1185               << "InputProcessBlockIntProducerG transitions " << testGlobalCache->transitions_
1186               << " but it was supposed to be " << testGlobalCache->expectedTransitions_;
1187         }
1188 
1189         if (testGlobalCache->sum_ != testGlobalCache->expectedSum_) {
1190           throw cms::Exception("UnexpectedValue") << "InputProcessBlockIntProducerG sum " << testGlobalCache->sum_
1191                                                   << " but it was supposed to be " << testGlobalCache->expectedSum_;
1192         }
1193       }
1194 
1195     private:
1196       edm::EDGetTokenT<IntProduct> getTokenBegin_;
1197       edm::EDGetTokenT<IntProduct> getTokenEnd_;
1198       edm::EDGetTokenT<IntProduct> getTokenBeginM_;
1199       edm::EDGetTokenT<IntProduct> getTokenEndM_;
1200     };
1201 
1202   }  // namespace stream
1203 }  // namespace edmtest
1204 std::atomic<unsigned int> edmtest::stream::GlobalIntProducer::m_count{0};
1205 std::atomic<unsigned int> edmtest::stream::RunIntProducer::m_count{0};
1206 std::atomic<unsigned int> edmtest::stream::LumiIntProducer::m_count{0};
1207 std::atomic<unsigned int> edmtest::stream::RunSummaryIntProducer::m_count{0};
1208 std::atomic<unsigned int> edmtest::stream::LumiSummaryIntProducer::m_count{0};
1209 std::atomic<unsigned int> edmtest::stream::TestBeginRunProducer::m_count{0};
1210 std::atomic<unsigned int> edmtest::stream::TestEndRunProducer::m_count{0};
1211 std::atomic<unsigned int> edmtest::stream::TestBeginLumiBlockProducer::m_count{0};
1212 std::atomic<unsigned int> edmtest::stream::TestEndLumiBlockProducer::m_count{0};
1213 std::atomic<unsigned int> edmtest::stream::GlobalIntProducer::cvalue_{0};
1214 std::atomic<unsigned int> edmtest::stream::RunIntProducer::cvalue_{0};
1215 std::atomic<unsigned int> edmtest::stream::LumiIntProducer::cvalue_{0};
1216 std::atomic<unsigned int> edmtest::stream::RunSummaryIntProducer::cvalue_{0};
1217 std::atomic<unsigned int> edmtest::stream::LumiSummaryIntProducer::cvalue_{0};
1218 std::atomic<unsigned int> edmtest::stream::TestBeginRunProducer::cvalue_{0};
1219 std::atomic<unsigned int> edmtest::stream::TestEndRunProducer::cvalue_{0};
1220 std::atomic<unsigned int> edmtest::stream::TestBeginLumiBlockProducer::cvalue_{0};
1221 std::atomic<unsigned int> edmtest::stream::TestEndLumiBlockProducer::cvalue_{0};
1222 std::atomic<bool> edmtest::stream::RunIntProducer::gbr{false};
1223 std::atomic<bool> edmtest::stream::RunIntProducer::ger{false};
1224 std::atomic<bool> edmtest::stream::LumiIntProducer::gbl{false};
1225 std::atomic<bool> edmtest::stream::LumiIntProducer::gel{false};
1226 std::atomic<bool> edmtest::stream::LumiIntProducer::bl{false};
1227 std::atomic<bool> edmtest::stream::LumiIntProducer::el{false};
1228 std::atomic<bool> edmtest::stream::RunSummaryIntProducer::gbr{false};
1229 std::atomic<bool> edmtest::stream::RunSummaryIntProducer::ger{false};
1230 std::atomic<bool> edmtest::stream::RunSummaryIntProducer::gbrs{false};
1231 std::atomic<bool> edmtest::stream::RunSummaryIntProducer::gers{false};
1232 std::atomic<bool> edmtest::stream::RunSummaryIntProducer::brs{false};
1233 std::atomic<bool> edmtest::stream::RunSummaryIntProducer::ers{false};
1234 std::atomic<bool> edmtest::stream::RunSummaryIntProducer::br{false};
1235 std::atomic<bool> edmtest::stream::RunSummaryIntProducer::er{false};
1236 std::atomic<unsigned int> edmtest::stream::LumiSummaryIntProducer::m_lumiSumCalls{0};
1237 std::atomic<bool> edmtest::stream::LumiSummaryIntProducer::gbl{false};
1238 std::atomic<bool> edmtest::stream::LumiSummaryIntProducer::gel{false};
1239 std::atomic<bool> edmtest::stream::LumiSummaryIntProducer::gbls{false};
1240 std::atomic<bool> edmtest::stream::LumiSummaryIntProducer::gels{false};
1241 std::atomic<bool> edmtest::stream::LumiSummaryIntProducer::bls{false};
1242 std::atomic<bool> edmtest::stream::LumiSummaryIntProducer::els{false};
1243 std::atomic<bool> edmtest::stream::LumiSummaryIntProducer::bl{false};
1244 std::atomic<bool> edmtest::stream::LumiSummaryIntProducer::el{false};
1245 std::atomic<bool> edmtest::stream::TestBeginRunProducer::gbr{false};
1246 std::atomic<bool> edmtest::stream::TestBeginRunProducer::gbrp{false};
1247 std::atomic<bool> edmtest::stream::TestBeginRunProducer::ger{false};
1248 std::atomic<bool> edmtest::stream::TestEndRunProducer::gbr{false};
1249 std::atomic<bool> edmtest::stream::TestEndRunProducer::ger{false};
1250 std::atomic<bool> edmtest::stream::TestEndRunProducer::p{false};
1251 std::atomic<bool> edmtest::stream::TestBeginLumiBlockProducer::gbl{false};
1252 std::atomic<bool> edmtest::stream::TestBeginLumiBlockProducer::gblp{false};
1253 std::atomic<bool> edmtest::stream::TestBeginLumiBlockProducer::gel{false};
1254 std::atomic<bool> edmtest::stream::TestEndLumiBlockProducer::gbl{false};
1255 std::atomic<bool> edmtest::stream::TestEndLumiBlockProducer::gel{false};
1256 std::atomic<bool> edmtest::stream::TestEndLumiBlockProducer::p{false};
1257 DEFINE_FWK_MODULE(edmtest::stream::GlobalIntProducer);
1258 DEFINE_FWK_MODULE(edmtest::stream::RunIntProducer);
1259 DEFINE_FWK_MODULE(edmtest::stream::LumiIntProducer);
1260 DEFINE_FWK_MODULE(edmtest::stream::RunSummaryIntProducer);
1261 DEFINE_FWK_MODULE(edmtest::stream::LumiSummaryIntProducer);
1262 DEFINE_FWK_MODULE(edmtest::stream::ProcessBlockIntProducer);
1263 DEFINE_FWK_MODULE(edmtest::stream::TestBeginProcessBlockProducer);
1264 DEFINE_FWK_MODULE(edmtest::stream::TestEndProcessBlockProducer);
1265 DEFINE_FWK_MODULE(edmtest::stream::ProcessBlockIntProducerNoGlobalCache);
1266 DEFINE_FWK_MODULE(edmtest::stream::TestBeginProcessBlockProducerNoGlobalCache);
1267 DEFINE_FWK_MODULE(edmtest::stream::TestEndProcessBlockProducerNoGlobalCache);
1268 DEFINE_FWK_MODULE(edmtest::stream::TestBeginRunProducer);
1269 DEFINE_FWK_MODULE(edmtest::stream::TestEndRunProducer);
1270 DEFINE_FWK_MODULE(edmtest::stream::TestBeginLumiBlockProducer);
1271 DEFINE_FWK_MODULE(edmtest::stream::TestEndLumiBlockProducer);
1272 DEFINE_FWK_MODULE(edmtest::stream::TestAccumulator);
1273 DEFINE_FWK_MODULE(edmtest::stream::InputProcessBlockIntProducer);
1274 DEFINE_FWK_MODULE(edmtest::stream::InputProcessBlockIntProducerG);