diff --git a/Simulation/Barcode/BarcodeInterfaces/BarcodeInterfaces/IBarcodeSvc.h b/Simulation/Barcode/BarcodeInterfaces/BarcodeInterfaces/IBarcodeSvc.h index d6e28fbbfc7a2bceb5c25732c83d57def8e1f0b2..f90638831cdd0b0df0d4b158dc42d8fc5d5414e8 100644 --- a/Simulation/Barcode/BarcodeInterfaces/BarcodeInterfaces/IBarcodeSvc.h +++ b/Simulation/Barcode/BarcodeInterfaces/BarcodeInterfaces/IBarcodeSvc.h @@ -33,6 +33,11 @@ namespace Barcode { /////////////////////////////////////////////////////////////////// public: + //TODO not fully implemented in Generic, Global, and Validation BarcodeSvcs + //only fully implemented in LegacyBarcodeSvc (only barcode service used in production) + virtual StatusCode initializeBarcodes() { return StatusCode::SUCCESS; }; + virtual StatusCode resetBarcodes() { return StatusCode::SUCCESS; }; + /// Creates the InterfaceID and interfaceID() method DeclareInterfaceID(IBarcodeSvc, 1 , 0); diff --git a/Simulation/Barcode/BarcodeServices/BarcodeServices/LegacyBarcodeSvc.h b/Simulation/Barcode/BarcodeServices/BarcodeServices/LegacyBarcodeSvc.h index 51c4eb5bc3b557eb90f41e491281ae7ea1b72029..341b1dea4da00a22e78c6cc1100481d9938cc3d5 100644 --- a/Simulation/Barcode/BarcodeServices/BarcodeServices/LegacyBarcodeSvc.h +++ b/Simulation/Barcode/BarcodeServices/BarcodeServices/LegacyBarcodeSvc.h @@ -13,7 +13,6 @@ #include <string> // FrameWork includes -#include "GaudiKernel/IIncidentListener.h" #include "GaudiKernel/ServiceHandle.h" #include "AthenaBaseComps/AthService.h" @@ -23,7 +22,8 @@ #include "BarcodeServices/BitCalculator.h" -class IIncidentSvc; +#include "tbb/concurrent_unordered_map.h" + namespace Barcode { @@ -36,7 +36,7 @@ namespace Barcode { @author Andreas.Salzburger -at- cern.ch , Elmar.Ritsch -at- cern.ch */ - class LegacyBarcodeSvc : public extends<AthService, IBarcodeSvc, IIncidentListener> { + class LegacyBarcodeSvc : public extends<AthService, IBarcodeSvc> { public: /** Constructor with parameters */ @@ -49,8 +49,11 @@ namespace Barcode { StatusCode initialize(); StatusCode finalize(); - /** Incident to reset the barcodes at the beginning of the event */ - void handle(const Incident& inc); + /** Construct and insert a new set of barcode members. To be called for every new thread. */ + virtual StatusCode initializeBarcodes() override; + + /** Reset barcodes. To be called at the beginning of each event. */ + virtual StatusCode resetBarcodes() override; /** Generate a new unique vertex barcode, based on the parent particle barcode and the physics process code causing the truth vertex*/ @@ -90,7 +93,6 @@ namespace Barcode { virtual inline bool hasBitCalculator() const { return (m_bitcalculator!=0); } private: - ServiceHandle<IIncidentSvc> m_incidentSvc; //!< IncidentSvc to catch begin of event and end of envent /** bitwise utility calculator for barcodes */ Barcode::BitCalculator* m_bitcalculator; @@ -110,6 +112,20 @@ namespace Barcode { /** throw error messages if a possible overflow is detected */ bool m_doUnderOverflowChecks; + + struct BarcodeInfo { + BarcodeInfo() = delete; + BarcodeInfo(VertexBarcode cv, ParticleBarcode cs) : currentVertex(cv), currentSecondary(cs) {}; + VertexBarcode currentVertex; + ParticleBarcode currentSecondary; + }; + + using LegacyBarcodeSvcThreadMap_t = tbb::concurrent_unordered_map + < std::thread::id, BarcodeInfo, std::hash<std::thread::id> >; + LegacyBarcodeSvcThreadMap_t m_bcThreadMap; + + BarcodeInfo& getBarcodeInfo() const; + }; diff --git a/Simulation/Barcode/BarcodeServices/src/LegacyBarcodeSvc.cxx b/Simulation/Barcode/BarcodeServices/src/LegacyBarcodeSvc.cxx index c9b816962b0ca764b71ee8ed21adfb58c1375ff2..633e382e0509406d02fe738649352720c98910f2 100644 --- a/Simulation/Barcode/BarcodeServices/src/LegacyBarcodeSvc.cxx +++ b/Simulation/Barcode/BarcodeServices/src/LegacyBarcodeSvc.cxx @@ -8,13 +8,11 @@ #include "BarcodeServices/LegacyBarcodeSvc.h" // framework include -#include "GaudiKernel/IIncidentSvc.h" /** Constructor **/ Barcode::LegacyBarcodeSvc::LegacyBarcodeSvc(const std::string& name,ISvcLocator* svc) : base_class(name,svc), - m_incidentSvc("IncidentSvc", name), m_bitcalculator(new Barcode::BitCalculator()), m_firstVertex(-200001), m_vertexIncrement(-1), @@ -45,33 +43,69 @@ Barcode::LegacyBarcodeSvc::~LegacyBarcodeSvc() StatusCode Barcode::LegacyBarcodeSvc::initialize() { ATH_MSG_VERBOSE ("initialize() ..."); + ATH_MSG_DEBUG( "LegacyBarcodeSvc start of initialize in thread ID: " << std::this_thread::get_id() ); - CHECK( m_incidentSvc.retrieve() ); - - // register to the incident service: BeginEvent needed for refresh of counter - m_incidentSvc->addListener( this, IncidentType::BeginEvent); + ATH_CHECK( this->initializeBarcodes() ); ATH_MSG_VERBOSE ("initialize() successful"); return StatusCode::SUCCESS; } +StatusCode Barcode::LegacyBarcodeSvc::initializeBarcodes() { + static std::mutex barcodeMutex; + std::lock_guard<std::mutex> barcodeLock(barcodeMutex); + ATH_MSG_DEBUG( name() << "::initializeBarcodes()" ); + + // look for pair containing barcode info using the thread ID + // if it doesn't exist, construct one and insert it. + const auto tid = std::this_thread::get_id(); + auto bcPair = m_bcThreadMap.find(tid); + if ( bcPair == m_bcThreadMap.end() ) { + auto result = m_bcThreadMap.insert( std::make_pair( tid, BarcodeInfo(m_currentVertex, m_currentSecondary)) ); + if (result.second) { + ATH_MSG_DEBUG( "initializeBarcodes: initialized new barcodes for thread ID " << tid ); + ATH_CHECK( this->resetBarcodes() ); + ATH_MSG_DEBUG( "initializeBarcodes: reset new barcodes for thread ID " << tid ); + } else { + ATH_MSG_ERROR( "initializeBarcodes: failed to initialize new barcode for thread ID " << tid ); + } + } else { + ATH_MSG_DEBUG( "initializeBarcodes: barcodes for this thread ID found, did not construct new" ); + ATH_CHECK( this->resetBarcodes() ); + ATH_MSG_DEBUG( "initializeBarcodes: reset existing barcodes for thread ID " << tid ); + } + return StatusCode::SUCCESS; +} + +//FIXME this should return an optional type, since returning the value of the end iterator is undefined behaviour (I think it causes a segfault). +Barcode::LegacyBarcodeSvc::BarcodeInfo& Barcode::LegacyBarcodeSvc::getBarcodeInfo() const { + const auto tid = std::this_thread::get_id(); + auto bcPair = m_bcThreadMap.find(tid); + if ( bcPair == m_bcThreadMap.end() ) { + ATH_MSG_ERROR( "getBarcodeInfo: failed to get BarcodeInfo for thread ID " << tid ); + return bcPair->second; + } else { + return bcPair->second; + } +} /** Generate a new unique vertex barcode, based on the parent particle barcode and the physics process code causing the truth vertex*/ Barcode::VertexBarcode Barcode::LegacyBarcodeSvc::newVertex( Barcode::ParticleBarcode /* parent */, Barcode::PhysicsProcessCode /* process */) { - m_currentVertex += m_vertexIncrement; + BarcodeInfo& bc = getBarcodeInfo(); + bc.currentVertex += m_vertexIncrement; // a naive underflog checking based on the fact that vertex // barcodes should never be positive - if ( m_doUnderOverflowChecks && (m_currentVertex > 0)) + if ( m_doUnderOverflowChecks && (bc.currentVertex > 0)) { ATH_MSG_ERROR("LegacyBarcodeSvc::newVertex(...)" << " will return a vertex barcode greater than 0: " - << m_currentVertex << ". Possibly Integer Underflow?"); + << bc.currentVertex << ". Possibly Integer Underflow?"); } - return m_currentVertex; + return bc.currentVertex; } @@ -81,19 +115,20 @@ Barcode::VertexBarcode Barcode::LegacyBarcodeSvc::newVertex( Barcode::ParticleBa Barcode::ParticleBarcode Barcode::LegacyBarcodeSvc::newSecondary( Barcode::ParticleBarcode /* parentBC */, Barcode::PhysicsProcessCode /* process */) { - m_currentSecondary += m_secondaryIncrement; + BarcodeInfo& bc = getBarcodeInfo(); + bc.currentSecondary += m_secondaryIncrement; // a naive overflow checking based on the fact that particle // barcodes should never be negative - if ( m_doUnderOverflowChecks && (m_currentSecondary < 0)) + if ( m_doUnderOverflowChecks && (bc.currentSecondary < 0)) { ATH_MSG_DEBUG("LegacyBarcodeSvc::newSecondary(...)" << " will return a particle barcode of less than 0: " - << m_currentSecondary << ". Reset to zero."); + << bc.currentSecondary << ". Reset to zero."); - m_currentSecondary = Barcode::fUndefinedBarcode; + bc.currentSecondary = Barcode::fUndefinedBarcode; } - return m_currentSecondary; + return bc.currentSecondary; } @@ -152,16 +187,13 @@ Barcode::ParticleBarcode Barcode::LegacyBarcodeSvc::particleGenerationIncrement( return m_particleGenerationIncrement; } - -/** Handle incident */ -void Barcode::LegacyBarcodeSvc::handle(const Incident& inc) +StatusCode Barcode::LegacyBarcodeSvc::resetBarcodes() { - if ( inc.type() == IncidentType::BeginEvent ) - { - ATH_MSG_VERBOSE("'BeginEvent' incident caught. Resetting Vertex and Particle barcode counters."); - m_currentVertex = m_firstVertex - m_vertexIncrement; - m_currentSecondary = m_firstSecondary - m_secondaryIncrement; - } + ATH_MSG_DEBUG( "resetBarcodes: resetting barcodes" ); + BarcodeInfo& bc = getBarcodeInfo(); + bc.currentVertex = m_firstVertex - m_vertexIncrement; + bc.currentSecondary = m_firstSecondary - m_secondaryIncrement; + return StatusCode::SUCCESS; } diff --git a/Simulation/G4Atlas/G4AtlasAlg/CMakeLists.txt b/Simulation/G4Atlas/G4AtlasAlg/CMakeLists.txt index fcd25f3b0d79a3985f6e5964735e21dbca503b45..73f0687c14d315c6e844c9ca89c67f787c143c68 100644 --- a/Simulation/G4Atlas/G4AtlasAlg/CMakeLists.txt +++ b/Simulation/G4Atlas/G4AtlasAlg/CMakeLists.txt @@ -21,7 +21,8 @@ atlas_depends_on_subdirs( PUBLIC Simulation/G4Atlas/G4AtlasTools Simulation/G4Sim/MCTruth Simulation/G4Sim/MCTruthBase - Simulation/ISF/ISF_Core/ISF_Interfaces) + Simulation/ISF/ISF_Core/ISF_Interfaces + Simulation/Barcode/BarcodeInterfaces) # External dependencies: find_package( CLHEP ) diff --git a/Simulation/G4Atlas/G4AtlasAlg/src/G4AtlasAlg.cxx b/Simulation/G4Atlas/G4AtlasAlg/src/G4AtlasAlg.cxx index e963695b27014340fe86dcff492831c901e99b8a..51497be66d0da8f120aa7c3652214e15e519a38e 100644 --- a/Simulation/G4Atlas/G4AtlasAlg/src/G4AtlasAlg.cxx +++ b/Simulation/G4Atlas/G4AtlasAlg/src/G4AtlasAlg.cxx @@ -273,7 +273,7 @@ StatusCode G4AtlasAlg::execute() } // tell TruthService we're starting a new event - ATH_CHECK( m_truthRecordSvc->initializeTruthCollection() ); //FIXME POINTLESS - THIS METHOD IS EMPTY IN MASTER + ATH_CHECK( m_truthRecordSvc->initializeTruthCollection() ); // Release GeoModel Geometry if necessary if (m_releaseGeoModel) { diff --git a/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx b/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx index 3ff3e891ecb595fc45683867478e103268d866dc..13c532fcd0f60614a4fa7d1f015c9345a85ccadf 100644 --- a/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx +++ b/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx @@ -127,6 +127,7 @@ StatusCode ISF::TruthSvc::finalize() /** Initialize the TruthSvc and the truthSvc */ StatusCode ISF::TruthSvc::initializeTruthCollection() { + ATH_CHECK( m_barcodeSvc->initializeBarcodes() ); return StatusCode::SUCCESS; } diff --git a/Simulation/ISF/ISF_Core/ISF_Services/test/TruthSvc_test.cxx b/Simulation/ISF/ISF_Core/ISF_Services/test/TruthSvc_test.cxx index 707f2b87aacb67627315aeb4ff50840c736a4724..b1d78f4c4bf0989ffab2f0001fc8fc889cdbd390 100644 --- a/Simulation/ISF/ISF_Core/ISF_Services/test/TruthSvc_test.cxx +++ b/Simulation/ISF/ISF_Core/ISF_Services/test/TruthSvc_test.cxx @@ -306,7 +306,7 @@ namespace ISFTesting { ASSERT_EQ( vtxPosition, generated->position() ); ASSERT_EQ( 1021, generated->id() ); - ASSERT_EQ( -2, generated->barcode() ); + ASSERT_EQ( -200001, generated->barcode() ); ASSERT_EQ( 1, generated->particles_in_size()); ASSERT_EQ( 0, generated->particles_out_size()); ASSERT_EQ( inParticle3, *(generated->particles_in_const_begin())); @@ -358,10 +358,10 @@ namespace ISFTesting { .WillOnce(::testing::Return(nullptr)); recordIncidentToMCTruth(ti); - HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-2); //Find a nicer way to get this. + HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-200001); //Find a nicer way to get this. ASSERT_EQ( vtxPosition, generated->position() ); ASSERT_EQ( 1021, generated->id() ); - ASSERT_EQ( -2, generated->barcode() ); // by construction at the moment + ASSERT_EQ( -200001, generated->barcode() ); // by construction at the moment ASSERT_EQ( 1, generated->particles_in_size()); ASSERT_EQ( 0, generated->particles_out_size()); ASSERT_EQ( inParticle3, *(generated->particles_in_const_begin())); @@ -404,7 +404,7 @@ namespace ISFTesting { .WillOnce(::testing::Return(inParticle3->barcode())); registerTruthIncident(ti); - HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-2); //Find a nicer way to get this. + HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-200001); //Find a nicer way to get this. HepMC::GenVertex* expectedVtx(nullptr); ASSERT_EQ( expectedVtx, generated); } @@ -454,10 +454,10 @@ namespace ISFTesting { .WillOnce(::testing::Return(inParticle3)); registerTruthIncident(ti); - HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-2); //Find a nicer way to get this. + HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-200001); //Find a nicer way to get this. ASSERT_EQ( vtxPosition, generated->position() ); ASSERT_EQ( 1021, generated->id() ); - ASSERT_EQ( -2, generated->barcode() ); // by construction at the moment + ASSERT_EQ( -200001, generated->barcode() ); // by construction at the moment ASSERT_EQ( 1, generated->particles_in_size()); ASSERT_EQ( 0, generated->particles_out_size()); ASSERT_EQ( inParticle3, *(generated->particles_in_const_begin())); @@ -524,10 +524,10 @@ namespace ISFTesting { .WillOnce(::testing::Return(false)); registerTruthIncident(ti); - HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-2); //Find a nicer way to get this. + HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-200001); //Find a nicer way to get this. ASSERT_EQ( vtxPosition, generated->position() ); ASSERT_EQ( 1021, generated->id() ); - ASSERT_EQ( -2, generated->barcode() ); // by construction at the moment + ASSERT_EQ( -200001, generated->barcode() ); // by construction at the moment ASSERT_EQ( 1, generated->particles_in_size()); ASSERT_EQ( 0, generated->particles_out_size()); ASSERT_EQ( inParticle3, *(generated->particles_in_const_begin())); @@ -597,10 +597,10 @@ namespace ISFTesting { .WillOnce(::testing::Return(true)); registerTruthIncident(ti); - HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-2); //Find a nicer way to get this. + HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-200001); //Find a nicer way to get this. ASSERT_EQ( vtxPosition, generated->position() ); ASSERT_EQ( 1021, generated->id() ); - ASSERT_EQ( -2, generated->barcode() ); // by construction at the moment + ASSERT_EQ( -200001, generated->barcode() ); // by construction at the moment ASSERT_EQ( 1, generated->particles_in_size()); ASSERT_EQ( inParticle3, *(generated->particles_in_const_begin())); ASSERT_EQ( 1, generated->particles_out_size());