diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ATLAS_CHECK_THREAD_SAFETY b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ATLAS_CHECK_THREAD_SAFETY new file mode 100644 index 0000000000000000000000000000000000000000..01505555eb60ae07b0b40fcf263867c5028246bf --- /dev/null +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ATLAS_CHECK_THREAD_SAFETY @@ -0,0 +1 @@ +InnerDetector/InDetValidation/InDetPhysValMonitoring diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/InDetPhysValMonitoringTool.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/InDetPhysValMonitoringTool.h index 6416676735700e9d4d91b6f45df3c9132b36ddcd..dfadc7d58e6669e138afc149837c3373565caa0f 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/InDetPhysValMonitoringTool.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/InDetPhysValMonitoringTool.h @@ -36,6 +36,7 @@ //Athena #include "AtlasDetDescr/AtlasDetectorID.h" +#include "CxxUtils/checker_macros.h" #include "InDetIdentifier/PixelID.h" #include "InDetIdentifier/SCT_ID.h" #include "InDetIdentifier/TRT_ID.h" @@ -138,7 +139,7 @@ private: ToolHandle<IInDetVertexTruthMatchTool> m_vtxValidTool; ToolHandle<IAthSelectionTool> m_truthSelectionTool; mutable std::mutex m_mutex; - mutable CutFlow m_truthCutFlow; + mutable CutFlow m_truthCutFlow ATLAS_THREAD_SAFE; // Guarded by m_mutex std::vector<int> m_prospectsMatched; float m_lowProb; float m_highProb; diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ResolutionHelper.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ResolutionHelper.h index c648fee859ce2b6b28e4c14f321e2a37f8c8ccaf..1175c1e92976895deba3cda00723309e3a68fd43 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ResolutionHelper.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/InDetPhysValMonitoring/ResolutionHelper.h @@ -16,6 +16,7 @@ #include "AthenaKernel/MsgStreamMember.h" #include "AthenaBaseComps/AthMsgStreamMacros.h" +#include "CxxUtils/checker_macros.h" class TH1; class TH2; @@ -157,7 +158,7 @@ namespace IDPVM { } /// Private message stream member - mutable Athena::MsgStreamMember m_msg; + mutable Athena::MsgStreamMember m_msg ATLAS_THREAD_SAFE; }; diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/DummyTrackSlimmingTool.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/DummyTrackSlimmingTool.h index de43273aec9d94b2face80c093098a58e3bcfb2f..b7d68141ceb0755af471c48b6e48b3c683369bcf 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/DummyTrackSlimmingTool.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/DummyTrackSlimmingTool.h @@ -8,6 +8,7 @@ #include "AthenaBaseComps/AthAlgTool.h" #include "TrkToolInterfaces/ITrackSlimmingTool.h" +#include "CxxUtils/checker_macros.h" class DummyTrackSlimmingTool: virtual public Trk::ITrackSlimmingTool, public AthAlgTool { @@ -35,7 +36,7 @@ public: @return A 'slimmed' version of 'track', where exactly what information is copied depends on how the tool is configured */ - virtual Trk::Track* slim(const Trk::Track& track) const override; + virtual Trk::Track* slim ATLAS_NOT_THREAD_SAFE (const Trk::Track& track) const override; virtual std::unique_ptr<Trk::Track> slimCopy(const Trk::Track& track) const override; virtual void slimTrack(Trk::Track&) const override; diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.cxx index e991f621e9c875c2f24ada557bd9b702a1753dff..f6c8abdba72a5326f7b737e8b2716097ea0459a8 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.cxx +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.cxx @@ -55,9 +55,8 @@ InDetPerfPlot_HitEfficiency::fill(const xAOD::TrackParticle& trkprt) { } const bool hitDetailsAvailable = trkprt.isAvailable<std::vector<int> >("measurement_region"); - static int warnCount(0); if (!hitDetailsAvailable) { - if (warnCount++ < 10) { + if (m_warnCount++ < 10) { ATH_MSG_WARNING("The HitEff plots dont see any data (note: only 10 warnings issued)"); } } else { diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.h index b33712b3595f3e1acbfd50ec5024d3469c8afecd..16e78e76b67dc4f9c3046bf315aff122fb5aed19 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitEfficiency.h @@ -22,6 +22,7 @@ // std includes +#include <atomic> #include <string> class TProfile; @@ -50,6 +51,8 @@ private: //TProfile* m_eff_hit_vs_eta[N_SUBDETECTORS][N_REGIONS]; TEfficiency* m_HitEfficiencyVsEta[N_SUBDETECTORS][N_REGIONS]; bool m_debug; + + mutable std::atomic<int> m_warnCount{0}; }; diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.cxx index bd8197261b65b4d75b145aae43a998ca3a857313..01e9163a65d99b88ec5bb64c8313d284bc23664b 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.cxx +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.cxx @@ -103,10 +103,9 @@ InDetPerfPlot_HitResidual::initializePlots() { void InDetPerfPlot_HitResidual::fill(const xAOD::TrackParticle& trkprt) { const static bool hitDetailsAvailable = trkprt.isAvailable<std::vector<int> >("measurement_region"); - static int warnCount(0); if (!hitDetailsAvailable) { - if (warnCount++ < 10) { + if (m_warnCount++ < 10) { ATH_MSG_WARNING("The hit res plots dont see any data (note:only 10 warnings issued)"); } } else { diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.h index b90f2f738b770c8b222743743ac6044bf637ab0a..9ecc146ec6de10fdf545be11ae46afb53cb1f066 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPerfPlot_HitResidual.h @@ -11,6 +11,7 @@ // std includes +#include <atomic> #include <string> #include <vector> #include "TProfile.h" @@ -60,6 +61,8 @@ private: TH1* m_pully[N_SUBDETECTORS][N_REGIONS]; TH1* m_phiWidth[N_SUBDETECTORS][N_REGIONS]; TH1* m_etaWidth[N_SUBDETECTORS][N_REGIONS]; + + mutable std::atomic<int> m_warnCount{0}; }; diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.cxx index c22fe1a3e2ebdf78caeb9da14a0da4475916f341..e95505f585b0b3e10b106dd9441b8ff45be5acee 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.cxx +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.cxx @@ -138,7 +138,7 @@ InDetPhysHitDecoratorAlg::decorateTrack(const xAOD::TrackParticle &particle, std::vector< SG::WriteDecorHandle<xAOD::TrackParticleContainer,std::vector<float> > > &float_decor, std::vector< SG::WriteDecorHandle<xAOD::TrackParticleContainer,std::vector<int> > > &int_decor) const { - static int trackNumber(0); + int trackNumber(0); typedef std::tuple<int, int, int, float, float, float, float, int, int, int> SingleResult_t; typedef std::vector<SingleResult_t> TrackResult_t; @@ -424,7 +424,6 @@ const Trk::TrackParameters* InDetPhysHitDecoratorAlg::getUnbiasedTrackParameters(const Trk::TrackParameters* trkParameters, const Trk::MeasurementBase* measurement, bool &isUnbiased) const { - static bool alreadyWarned(false); const Trk::TrackParameters* unbiasedTrkParameters(trkParameters); if (!m_updatorHandle.empty() && (isUnbiased)) { @@ -437,11 +436,11 @@ InDetPhysHitDecoratorAlg::getUnbiasedTrackParameters(const Trk::TrackParameters* ATH_MSG_INFO( "Could not get unbiased track parameters, use normal parameters" ); isUnbiased = false; } - } else if (not alreadyWarned) { + } else if (not m_alreadyWarned) { // warn only once! ATH_MSG_WARNING("TrackParameters contain no covariance, unbiased track states can not be calculated " "(ie. pulls and residuals will be too small)" ); - alreadyWarned = true; + m_alreadyWarned = true; isUnbiased = false; } else { isUnbiased = false; diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.h index 14c11c5f2193e8f78106e93eb0ad1b7c972ef8cd..a399d7a7a27d9db40b9fbc66aa56d425cf7dc086 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysHitDecoratorAlg.h @@ -11,6 +11,7 @@ * @date 27 March 2014 **/ // STL includes +#include <mutex> #include <string> #include "AthenaBaseComps/AthReentrantAlgorithm.h" #include "GaudiKernel/ToolHandle.h" @@ -88,6 +89,7 @@ private: const double m_ptThreshold; bool m_doUpgrade; + mutable std::atomic<bool> m_alreadyWarned{false}; // the following help identify a surface in the detector const AtlasDetectorID* m_idHelper; const PixelID* m_pixelID; diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.cxx index 26ae809920948eb5bab2f728035ea71a20dac15d..678bcdf689dbbc9b9e4e6a7ad61b8ba435c8a3bb 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.cxx +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.cxx @@ -121,15 +121,14 @@ InDetPhysValTruthDecoratorAlg::decorateTruth(const xAOD::TruthParticle& particle return false; } - static bool errorEmitted(false); const xAOD::TruthVertex* ptruthVertex(0); try{ ptruthVertex = particle.prodVtx(); } catch (const std::exception& e) { - if (not errorEmitted) { + if (not m_errorEmitted) { ATH_MSG_WARNING("A non existent production vertex was requested in calculating the track parameters d0 etc"); } - errorEmitted = true; + m_errorEmitted = true; return false; } if (!ptruthVertex) { diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.h index e64769abcfb26161cbe5f9578f43dee8b13a0e86..2e07f752ba705c575116b2cb6db84ea8448a0cf4 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPhysValTruthDecoratorAlg.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ #ifndef INDETPHYSVALMONITORING_INDETPHYSVALTRUTHDECORATORTOOL_H @@ -23,6 +23,8 @@ #include "GaudiKernel/EventContext.h" #include "InDetPhysValMonitoring/IAthSelectionTool.h" #include "InDetPhysValMonitoring/CutFlow.h" +#include "CxxUtils/checker_macros.h" +#include <atomic> #include <utility> #include <vector> @@ -51,7 +53,9 @@ private: {this,"TruthSelectionTool","",""}; mutable std::mutex m_mutex; - mutable CutFlow m_cutFlow; + mutable CutFlow m_cutFlow ATLAS_THREAD_SAFE; // Guarded by m_mutex + + mutable std::atomic<bool> m_errorEmitted{false}; ///TruthParticle container's name needed to create decorators SG::ReadHandleKey<xAOD::TruthParticleContainer> m_truthParticleName diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPlotBase.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPlotBase.h index bdc44e8ea9866ec8c9594b5bfa57d339f3fc596c..4e0dbba4850223286b161a7bddde2db4054dda54 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPlotBase.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/InDetPlotBase.h @@ -12,6 +12,7 @@ #include "TrkValHistUtils/PlotBase.h" #include "AthenaKernel/MsgStreamMember.h" #include "AthenaBaseComps/AthMsgStreamMacros.h" +#include "CxxUtils/checker_macros.h" #include "InDetPhysValMonitoring/SingleHistogramDefinition.h" // to make available to children #include <string> @@ -98,7 +99,7 @@ protected: } /// Private message stream member - mutable Athena::MsgStreamMember m_msg; + mutable Athena::MsgStreamMember m_msg ATLAS_THREAD_SAFE; private: IHistogramDefinitionSvc* m_histoDefSvc; }; diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.cxx index 41d23e837a7c44d46f62f9f113ef60244b0941fe..03d21ec828faacde4ffcf62a16a77cdfb12523b0 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.cxx +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ // // ReadFromXmlDom.cxx @@ -20,6 +20,19 @@ #include <cmath> #include <regex> +#include "CxxUtils/checker_macros.h" +ATLAS_NO_CHECK_FILE_THREAD_SAFETY; +// The following warning message is given if checked: +// warning: Use of static expression 'xercesc_3_1::XMLPlatformUtils::fgMemoryManager' +// of type 'xercesc_3_1::MemoryManager*' within function +// 'toNative(const XMLCh*)::<lambda(char*)>' may not be thread-safe. +// +// https://xerces.apache.org/xerces-c/faq-parse-3.html#faq-6 +// Is Xerces-C++ thread-safe? +// The answer is yes if you observe the following rules for using Xerces-C++ +// in a multi-threaded environment: +// ... ... + namespace { bool validAxisName(const std::string& proposedName, const std::array<std::string, 3>& allowedNames) { diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.h index 96d9e0b9406f56c2d88c11e0468f85653c57c27b..bb1a7f53c677093f44fb6553ceabe95b1d84e86a 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/ReadFromXmlDom.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ // // ReadFromXmlDom.h @@ -15,7 +15,18 @@ #include "InDetPhysValMonitoring/SingleHistogramDefinition.h" #include <xercesc/parsers/XercesDOMParser.hpp> - +#include "CxxUtils/checker_macros.h" +ATLAS_NO_CHECK_FILE_THREAD_SAFETY; +// The following warning message is given if checked: +// warning: Use of static expression 'xercesc_3_1::XMLPlatformUtils::fgMemoryManager' +// of type 'xercesc_3_1::MemoryManager*' within function +// 'toNative(const XMLCh*)::<lambda(char*)>' may not be thread-safe. +// +// https://xerces.apache.org/xerces-c/faq-parse-3.html#faq-6 +// Is Xerces-C++ thread-safe? +// The answer is yes if you observe the following rules for using Xerces-C++ +// in a multi-threaded environment: +// ... ... class ReadFromXmlDom: public IReadHistoDef { public: @@ -35,4 +46,4 @@ private: SingleHistogramDefinition parseTProfileText(const std::string& line); SingleHistogramDefinition parseXmlElement(const xercesc::DOMElement* element); }; -#endif /* ReadFromXmlDom_h */ \ No newline at end of file +#endif /* ReadFromXmlDom_h */ diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.cxx index a2e003ff8cf59a643c2fd2e8eb187aecf1fe0188..2caf893d1afbfe749ec9c6316c7a37b028327070 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.cxx +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.cxx @@ -135,6 +135,7 @@ TrackTruthSelectionTool::accept(const xAOD::TruthParticle* p) const { if (m_pdgId > -1) { acceptData.setCutResult("pdgId", (std::fabs(p->pdgId()) == m_pdgId));// 3-18-16 normally on, disabled for testing } + std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_numTruthPassedCuts // Book keep cuts for (const auto& cut : m_cuts) { unsigned int pos = acceptData.getCutPosition(cut.first); diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.h index cbb5119fc43ae7e985986ba32848e48f97efe37f..5d534336a6ae83d2b0035e762b95c5732f117ef6 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/TrackTruthSelectionTool.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ #ifndef INDETPHYSVALMONITORING_TRACKTRUTHSELECTORTOOL_H @@ -10,6 +10,8 @@ #include "xAODTruth/TruthParticle.h" #include "AsgTools/AsgTool.h" +#include <atomic> +#include <mutex> class TrackTruthSelectionTool: public virtual ::IAsgSelectionTool, @@ -29,9 +31,10 @@ public: private: asg::AcceptInfo m_accept; std::vector<std::pair<std::string, std::string> > m_cuts; - mutable ULong64_t m_numTruthProcessed; // !< a counter of the number of tracks proccessed - mutable ULong64_t m_numTruthPassed; // !< a counter of the number of tracks that passed all cuts - mutable std::vector<ULong64_t> m_numTruthPassedCuts; // !< tracks the number of tracks that passed each cut family + mutable std::atomic<ULong64_t> m_numTruthProcessed; // !< a counter of the number of tracks proccessed + mutable std::atomic<ULong64_t> m_numTruthPassed; // !< a counter of the number of tracks that passed all cuts + mutable std::vector<ULong64_t> m_numTruthPassedCuts ATLAS_THREAD_SAFE; // !< tracks the number of tracks that passed each cut family. Guarded by m_mutex + mutable std::mutex m_mutex; // !< To guard m_numTruthPassedCuts // Cut values; float m_maxEta; diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.cxx index 23a22447c35ed9e4c8c60ac1258ce1e499b49f12..ce3e5662fdd5ff7b63f0e1ae93437bbb73d02765 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.cxx +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.cxx @@ -192,50 +192,52 @@ dRMatchingTool::sortVectors(const T* container, void dRMatchingTool::checkCacheTrackParticles(const xAOD::TrackParticleContainer* trackParticles, + CacheEntry* ent, bool (* trackSelectionTool)(const xAOD::TrackParticle*)) const { // Check whether to cache. - if (*trackParticles == m_baseTrackContainer) { + if (*trackParticles == ent->m_baseTrackContainer) { return; } // Clear existing cache. - clearTrackParticles(); + clearTrackParticles(ent); // Cache track particles. sortVectors<xAOD::TrackParticleContainer, xAOD::TrackParticle>(trackParticles, - m_trackParticlesSortedPt, - m_trackParticlesSortedEta, - m_trackParticlesSortedPhi, + ent->m_trackParticlesSortedPt, + ent->m_trackParticlesSortedEta, + ent->m_trackParticlesSortedPhi, trackSelectionTool); // Store copy of base track container. - m_baseTrackContainer = *trackParticles; + ent->m_baseTrackContainer = *trackParticles; return; } void dRMatchingTool::checkCacheTruthParticles(const xAOD::TruthParticleContainer* truthParticles, + CacheEntry* ent, bool (* truthSelectionTool)(const xAOD::TruthParticle*)) const { // Check whether to cache. - if (*truthParticles == m_baseTruthContainer) { + if (*truthParticles == ent->m_baseTruthContainer) { return; } // Clear existing cache. - clearTruthParticles(); + clearTruthParticles(ent); // Cache truth particles. sortVectors<xAOD::TruthParticleContainer, xAOD::TruthParticle>(truthParticles, - m_truthParticlesSortedPt, - m_truthParticlesSortedEta, - m_truthParticlesSortedPhi, + ent->m_truthParticlesSortedPt, + ent->m_truthParticlesSortedEta, + ent->m_truthParticlesSortedPhi, truthSelectionTool); // Store copy of base truth container. - m_baseTruthContainer = *truthParticles; + ent->m_baseTruthContainer = *truthParticles; return; } @@ -245,9 +247,10 @@ bool dRMatchingTool::sortedMatch(const U* p, std::vector< const V* >& vec_pt, std::vector< const V* >& vec_eta, - std::vector< const V* >& vec_phi) const { + std::vector< const V* >& vec_phi, + float& dRmin) const { // (Re-)set variables. - m_dRmin = 9999.; + dRmin = 9999.; // Perform search in cached vectors. auto it_pt_lower = m_pTResMax < 0 ? vec_pt.begin() : @@ -363,8 +366,8 @@ dRMatchingTool::sortedMatch(const U* p, bool passes = false; for (const V* other : set) { float dR = comp_deltaR(p, other); - m_dRmin = (dR < m_dRmin ? dR : m_dRmin); - passes |= m_dRmin < m_dRmax; + dRmin = (dR < dRmin ? dR : dRmin); + passes |= dRmin < m_dRmax; } return passes; @@ -376,14 +379,20 @@ dRMatchingTool::accept(const xAOD::TrackParticle* track, bool (* truthSelectionTool)(const xAOD::TruthParticle*)) const { asg::AcceptData acceptData (&m_accept); + std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_numPassedCuts and m_cache + const EventContext& ctx{Gaudi::Hive::currentContext()}; + CacheEntry* ent{m_cache.get(ctx)}; + ent->check(ctx.evt()); + // Determine whether to cache current truth particle container - checkCacheTruthParticles(truthParticles, truthSelectionTool); + checkCacheTruthParticles(truthParticles, ent, truthSelectionTool); bool passes = sortedMatch<xAOD::TrackParticle, xAOD::TruthParticle>(track, - m_truthParticlesSortedPt, - m_truthParticlesSortedEta, - m_truthParticlesSortedPhi); + ent->m_truthParticlesSortedPt, + ent->m_truthParticlesSortedEta, + ent->m_truthParticlesSortedPhi, + ent->m_dRmin); // Set cut values. if (m_dRmax > -1) { @@ -415,14 +424,20 @@ dRMatchingTool::accept(const xAOD::TruthParticle* truth, bool (* trackSelectionTool)(const xAOD::TrackParticle*)) const { asg::AcceptData acceptData (&m_accept); + std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_numPassedCuts and m_cache + const EventContext& ctx{Gaudi::Hive::currentContext()}; + CacheEntry* ent{m_cache.get(ctx)}; + ent->check(ctx.evt()); + // Determine whether to cache current track particle container - checkCacheTrackParticles(trackParticles, trackSelectionTool); + checkCacheTrackParticles(trackParticles, ent, trackSelectionTool); bool passes = sortedMatch<xAOD::TruthParticle, xAOD::TrackParticle>(truth, - m_trackParticlesSortedPt, - m_trackParticlesSortedEta, - m_trackParticlesSortedPhi); + ent->m_trackParticlesSortedPt, + ent->m_trackParticlesSortedEta, + ent->m_trackParticlesSortedPhi, + ent->m_dRmin); // Set cut values. if (m_dRmax > -1) { @@ -453,7 +468,13 @@ dRMatchingTool::acceptLegacy(const xAOD::TrackParticle* p, const xAOD::TruthParticleContainer* truthParticles, bool (* truthSelectionTool)(const xAOD::TruthParticle*)) const { asg::AcceptData acceptData (&m_accept); - m_dRmin = 9999.; + + std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_numPassedCuts and m_cache + const EventContext& ctx{Gaudi::Hive::currentContext()}; + CacheEntry* ent{m_cache.get(ctx)}; + ent->check(ctx.evt()); + + ent->m_dRmin = 9999.; // Define variables. const unsigned int Ncuts(m_cuts.size()); @@ -492,7 +513,7 @@ dRMatchingTool::acceptLegacy(const xAOD::TrackParticle* p, // If the current truth particle was matched, check minimal dR. if (passesThis) { - m_dRmin = (dR < m_dRmin ? dR : m_dRmin); + ent->m_dRmin = (dR < ent->m_dRmin ? dR : ent->m_dRmin); } } @@ -526,7 +547,13 @@ dRMatchingTool::acceptLegacy(const xAOD::TruthParticle* p, bool (* trackSelectionTool)(const xAOD::TrackParticle*)) const { // Reset the results. asg::AcceptData acceptData (&m_accept); - m_dRmin = 9999.; + + std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_numPassedCuts and m_cache + const EventContext& ctx{Gaudi::Hive::currentContext()}; + CacheEntry* ent{m_cache.get(ctx)}; + ent->check(ctx.evt()); + + ent->m_dRmin = 9999.; // Define variables. const unsigned int Ncuts(m_cuts.size()); @@ -565,7 +592,7 @@ dRMatchingTool::acceptLegacy(const xAOD::TruthParticle* p, // If the current track particle was matched, check minimal dR. if (passesThis) { - m_dRmin = (dR < m_dRmin ? dR : m_dRmin); + ent->m_dRmin = (dR < ent->m_dRmin ? dR : ent->m_dRmin); } } @@ -615,5 +642,10 @@ dRMatchingTool::finalize() { float dRMatchingTool::dRmin() const { - return m_dRmin; + std::lock_guard<std::mutex> lock{m_mutex}; // To guard m_cache + const EventContext& ctx{Gaudi::Hive::currentContext()}; + CacheEntry* ent{m_cache.get(ctx)}; + ent->check(ctx.evt()); + + return ent->m_dRmin; } diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.h index b9827c94fcdd486d94ef28d0f5c6b095b86c9965..8cb919089d08b608e17f56235fcea4d10579f4b7 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/dRMatchingTool.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ #ifndef INDETPHYSVALMONITORING_DRMATCHINGTOOL_H @@ -13,12 +13,16 @@ */ // STL include(s) +#include <atomic> #include <cmath> /* std::fabs, sqrt, pow */ #include <algorithm> /* std::all_of (C++11), std::sort, std::lower_bound, std::upper_bound, std::set_intersection */ #include <iterator> /* std::back_inserter */ +#include <mutex> // ATLAS software include(s) #include "AthenaBaseComps/AthAlgTool.h" +#include "AthenaKernel/SlotSpecificObj.h" +#include "CxxUtils/checker_macros.h" #include "PATCore/IAsgSelectionTool.h" #include "AsgTools/AsgTool.h" @@ -121,29 +125,71 @@ public: // Accessor for the minimal dR from the latest matching of either type. float dRmin() const; protected: + // Struct for event cache + struct CacheEntry { + EventContext::ContextEvt_t m_evt{EventContext::INVALID_CONTEXT_EVT}; + + // The minimal dR for latest successful matching of either type. + float m_dRmin = 9999.; + + // Copy of the xAOD::TruthParticleContainer used to perform the caching. A + // copy, rather than a pointer or reference, is necessary to check when a new + // container is encountered (i.e. when a new event is processed). + xAOD::TruthParticleContainer m_baseTruthContainer; + // Copy of the xAOD::TrackParticleContainer used to perform the caching. + xAOD::TrackParticleContainer m_baseTrackContainer; + + // Cached vectors of the xAOD::TruthParticles in m_baseTruthContainer, sorted + // in ascending order accoring to their pT, eta, and phi, resp. + std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedPt; + std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedEta; + std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedPhi; + // Cached vectors of the xAOD::TrackParticles in m_baseTrackContainer, sorted + // in ascending order accoring to their pT, eta, and phi, resp. + std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedPt; + std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedEta; + std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedPhi; + + void check(EventContext::ContextEvt_t evt) { + // Check event number and reset variables if a new event + if (m_evt==evt) return; + + m_dRmin = 9999.; + m_truthParticlesSortedPt.clear(); + m_truthParticlesSortedEta.clear(); + m_truthParticlesSortedPhi.clear(); + m_trackParticlesSortedPt.clear(); + m_trackParticlesSortedEta.clear(); + m_trackParticlesSortedPhi.clear(); + m_evt = evt; + } + }; + /// Internal method(s). // Cache track particles. void checkCacheTrackParticles(const xAOD::TrackParticleContainer* trackParticles, + CacheEntry* ent, bool (* trackSelectionTool)(const xAOD::TrackParticle*) = nullptr) const; // Cache truth particles. void checkCacheTruthParticles(const xAOD::TruthParticleContainer* truthParticles, + CacheEntry* ent, bool (* truthSelectionTool)(const xAOD::TruthParticle*) = nullptr) const; // Clear cached track particle arrays. inline void - clearTrackParticles() const { - m_trackParticlesSortedPt.clear(); - m_trackParticlesSortedEta.clear(); - m_trackParticlesSortedPhi.clear(); + clearTrackParticles(CacheEntry* ent) const { + ent->m_trackParticlesSortedPt.clear(); + ent->m_trackParticlesSortedEta.clear(); + ent->m_trackParticlesSortedPhi.clear(); return; } // Clear cached truth particle arrays. inline void - clearTruthParticles() const { - m_truthParticlesSortedPt.clear(); - m_truthParticlesSortedEta.clear(); - m_truthParticlesSortedPhi.clear(); + clearTruthParticles(CacheEntry* ent) const { + ent->m_truthParticlesSortedPt.clear(); + ent->m_truthParticlesSortedEta.clear(); + ent->m_truthParticlesSortedPhi.clear(); return; } @@ -162,7 +208,8 @@ protected: bool sortedMatch(const U* p, std::vector< const V* >& vec_pt, std::vector< const V* >& vec_eta, - std::vector< const V* >& vec_phi) const; + std::vector< const V* >& vec_phi, + float& dRmin) const; private: /// Data member(s). // AcceptInfo object. @@ -171,35 +218,19 @@ private: std::vector<std::pair<std::string, std::string> > m_cuts; // Counters. - mutable ULong64_t m_numProcessed; // !< a counter of the number of tracks proccessed - mutable ULong64_t m_numPassed; // !< a counter of the number of tracks that passed all cuts - mutable std::vector<ULong64_t> m_numPassedCuts; // !< tracks the number of tracks that passed each cut family + mutable std::atomic<ULong64_t> m_numProcessed; // !< a counter of the number of tracks proccessed + mutable std::atomic<ULong64_t> m_numPassed; // !< a counter of the number of tracks that passed all cuts + mutable std::vector<ULong64_t> m_numPassedCuts ATLAS_THREAD_SAFE; // !< tracks the number of tracks that passed each cut family. Guarded by m_mutex + mutable std::mutex m_mutex; // !< To guard m_numPassedCuts and m_cache /// Cut vales. // The maximal dR-distance allowed for successful matching. float m_dRmax; // The maximal pT-resolution allowed for successful matching. float m_pTResMax; - // The minimal dR for latest successful matching of either type. - mutable float m_dRmin = 9999.; - - // Copy of the xAOD::TruthParticleContainer used to perform the caching. A - // copy, rather than a pointer or reference, is necessary to check when a new - // container is encountered (i.e. when a new event is processed). - mutable xAOD::TruthParticleContainer m_baseTruthContainer; - // Copy of the xAOD::TrackParticleContainer used to perform the caching. - mutable xAOD::TrackParticleContainer m_baseTrackContainer; - - // Cached vectors of the xAOD::TruthParticles in m_baseTruthContainer, sorted - // in ascending order accoring to their pT, eta, and phi, resp. - mutable std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedPt; - mutable std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedEta; - mutable std::vector< const xAOD::TruthParticle* > m_truthParticlesSortedPhi; - // Cached vectors of the xAOD::TrackParticles in m_baseTrackContainer, sorted - // in ascending order accoring to their pT, eta, and phi, resp. - mutable std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedPt; - mutable std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedEta; - mutable std::vector< const xAOD::TrackParticle* > m_trackParticlesSortedPhi; + + // Event cache + mutable SG::SlotSpecificObj<CacheEntry> m_cache ATLAS_THREAD_SAFE; // Guarded by m_mutex }; #endif // > !INDETPHYSVALMONITORING_DRMATCHINGTOOL_H diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/xmlUtilities.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/xmlUtilities.h index 1236432ded767903933389e7177185a91d83f98b..409ddac07fbda4f14b9566dd7468076bbd985077 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/xmlUtilities.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/src/xmlUtilities.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ // // xmlUtilities.h @@ -16,7 +16,18 @@ #include <xercesc/util/XMLString.hpp> // transcode #include <xercesc/dom/DOM.hpp> // DOMxxx - +#include "CxxUtils/checker_macros.h" +ATLAS_NO_CHECK_FILE_THREAD_SAFETY; +// The following warning message is given if checked: +// warning: Use of static expression 'xercesc_3_1::XMLPlatformUtils::fgMemoryManager' +// of type 'xercesc_3_1::MemoryManager*' within function +// 'toNative(const XMLCh*)::<lambda(char*)>' may not be thread-safe. +// +// https://xerces.apache.org/xerces-c/faq-parse-3.html#faq-6 +// Is Xerces-C++ thread-safe? +// The answer is yes if you observe the following rules for using Xerces-C++ +// in a multi-threaded environment: +// ... ... typedef std::basic_string<XMLCh>XercesString; inline XercesString diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/HistogramDefinitionSvc_test.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/HistogramDefinitionSvc_test.cxx index d9e716903366b96719cc691c055d11f5661ed289..a1f099bf11024a67969d7598b23a94228306f970 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/HistogramDefinitionSvc_test.cxx +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/HistogramDefinitionSvc_test.cxx @@ -23,6 +23,10 @@ #include "../InDetPhysValMonitoring/SingleHistogramDefinition.h" #include <utility> //std::pair +#include "CxxUtils/checker_macros.h" +ATLAS_NO_CHECK_FILE_THREAD_SAFETY; +// This test uses global svcLoc and hDefSvc, and is not thread safe. + static const std::string testJobOptionsFile("IDPVM_Test.txt"); struct GaudiKernelFixture:public IDPVM_GaudiFixtureBase{ @@ -109,4 +113,4 @@ BOOST_AUTO_TEST_SUITE(HistogramDefinitionSvcTest) } BOOST_AUTO_TEST_SUITE_END() - \ No newline at end of file + diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/IDPVM_GaudiFixtureBase.h b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/IDPVM_GaudiFixtureBase.h index 4b8296fe0acd689a620a28d76e681dec19eae5d5..31e77d8f716e4611cdee284a77bdbc695178edda 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/IDPVM_GaudiFixtureBase.h +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/IDPVM_GaudiFixtureBase.h @@ -19,6 +19,10 @@ #include "CxxUtils/ubsan_suppress.h" #include <string> +#include "CxxUtils/checker_macros.h" +ATLAS_NO_CHECK_FILE_THREAD_SAFETY; +// This test uses static gaudiIsInitialised, and is not thread safe. + struct IDPVM_GaudiFixtureBase{ ISvcLocator* svcLoc{}; static bool gaudiIsInitialised; diff --git a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/XmlEntityInclusion_test.cxx b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/XmlEntityInclusion_test.cxx index d02e10db624b89cbca060e7396455d50cb2361a6..107e534d81d2f084827102ca132f04c01cd5ed7b 100644 --- a/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/XmlEntityInclusion_test.cxx +++ b/InnerDetector/InDetValidation/InDetPhysValMonitoring/test/XmlEntityInclusion_test.cxx @@ -23,6 +23,10 @@ #include "../InDetPhysValMonitoring/SingleHistogramDefinition.h" #include <utility> //std::pair +#include "CxxUtils/checker_macros.h" +ATLAS_NO_CHECK_FILE_THREAD_SAFETY; +// This test uses global svcLoc and hDefSvc, and is not thread safe. + static const std::string entityInclusionOptions("XmlEntityInclusionOptions.txt"); /* The job options refer to an xml file 'entityMaster.xml' which contains