File indexing completed on 2023-10-25 10:04:21
0001 #include <memory>
0002
0003 #include "SimG4Core/Application/interface/OscarMTMasterThread.h"
0004 #include "FWCore/Utilities/interface/Exception.h"
0005 #include "FWCore/Framework/interface/ConsumesCollector.h"
0006
0007 #include "SimG4Core/Application/interface/RunManagerMT.h"
0008 #include "SimG4Core/Geometry/interface/CustomUIsession.h"
0009
0010 #include "G4PhysicalVolumeStore.hh"
0011
0012 OscarMTMasterThread::OscarMTMasterThread(const edm::ParameterSet& iConfig)
0013 : m_pGeoFromDD4hep(iConfig.getParameter<bool>("g4GeometryDD4hepSource")),
0014 m_masterThreadState(ThreadState::NotExist) {
0015
0016 std::unique_lock<std::mutex> lk(m_threadMutex);
0017
0018 edm::LogVerbatim("SimG4CoreApplication")
0019 << "OscarMTMasterThread: creating master thread DD4hep: " << m_pGeoFromDD4hep;
0020
0021
0022 m_masterThread = std::thread([&]() {
0023
0024
0025 std::unique_ptr<CustomUIsession> uiSession;
0026
0027
0028 std::unique_lock<std::mutex> lk2(m_threadMutex);
0029
0030 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: initializing RunManagerMT";
0031
0032
0033 uiSession = std::make_unique<CustomUIsession>();
0034
0035
0036 m_runManagerMaster = std::make_shared<RunManagerMT>(iConfig);
0037
0038
0039
0040 bool isG4Alive = false;
0041 while (true) {
0042
0043 m_mainCanProceed = true;
0044 edm::LogVerbatim("OscarMTMasterThread") << "Master thread: State loop, notify main thread";
0045 m_notifyMainCv.notify_one();
0046
0047
0048 m_masterCanProceed = false;
0049 edm::LogVerbatim("OscarMTMasterThread") << "Master thread: State loop, starting wait";
0050 m_notifyMasterCv.wait(lk2, [&] { return m_masterCanProceed; });
0051
0052
0053
0054 edm::LogVerbatim("OscarMTMasterThread")
0055 << "Master thread: Woke up, state is " << static_cast<int>(m_masterThreadState);
0056 if (m_masterThreadState == ThreadState::BeginRun) {
0057
0058 edm::LogVerbatim("OscarMTMasterThread") << "Master thread: Initializing Geant4";
0059 m_runManagerMaster->initG4(m_pDDD, m_pDD4hep, m_pTable);
0060 isG4Alive = true;
0061 } else if (m_masterThreadState == ThreadState::EndRun) {
0062
0063 edm::LogVerbatim("OscarMTMasterThread") << "Master thread: Stopping Geant4";
0064 m_runManagerMaster->stopG4();
0065 isG4Alive = false;
0066 } else if (m_masterThreadState == ThreadState::Destruct) {
0067 edm::LogVerbatim("OscarMTMasterThread") << "Master thread: Breaking out of state loop";
0068 if (isG4Alive)
0069 throw cms::Exception("LogicError") << "OscarMTMasterThread: Geant4 is still alive, master thread "
0070 << "state must be set to EndRun before Destruct";
0071 break;
0072 } else {
0073 throw cms::Exception("LogicError")
0074 << "OscarMTMasterThread: Illegal master thread state " << static_cast<int>(m_masterThreadState);
0075 }
0076 }
0077
0078
0079
0080 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: start RunManagerMT destruction";
0081
0082
0083 m_runManagerMaster.reset();
0084 G4PhysicalVolumeStore::Clean();
0085
0086 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: physics and geometry are cleaned";
0087 lk2.unlock();
0088 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: Master thread is finished";
0089 });
0090
0091
0092
0093 m_mainCanProceed = false;
0094 LogDebug("OscarMTMasterThread") << "Main thread: Signal master for initialization";
0095 m_notifyMainCv.wait(lk, [&]() { return m_mainCanProceed; });
0096
0097 lk.unlock();
0098 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: Master thread is constructed";
0099 }
0100
0101 OscarMTMasterThread::~OscarMTMasterThread() {
0102 if (!m_stopped) {
0103 stopThread();
0104 }
0105 }
0106
0107 void OscarMTMasterThread::callConsumes(edm::ConsumesCollector&& iC) const {
0108 if (m_hasToken) {
0109 return;
0110 }
0111 if (m_pGeoFromDD4hep) {
0112 m_DD4hep = iC.esConsumes<cms::DDCompactView, IdealGeometryRecord, edm::Transition::BeginRun>();
0113 } else {
0114 m_DDD = iC.esConsumes<DDCompactView, IdealGeometryRecord, edm::Transition::BeginRun>();
0115 }
0116 m_PDT = iC.esConsumes<HepPDT::ParticleDataTable, PDTRecord, edm::Transition::BeginRun>();
0117 m_hasToken = true;
0118 }
0119
0120 void OscarMTMasterThread::beginRun(const edm::EventSetup& iSetup) const {
0121 std::lock_guard<std::mutex> lk(m_protectMutex);
0122 std::unique_lock<std::mutex> lk2(m_threadMutex);
0123 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread::beginRun";
0124
0125 if (m_firstRun) {
0126 if (m_pGeoFromDD4hep) {
0127 m_pDD4hep = &(*iSetup.getTransientHandle(m_DD4hep));
0128 } else {
0129 m_pDDD = &(*iSetup.getTransientHandle(m_DDD));
0130 }
0131 m_pTable = &iSetup.getData(m_PDT);
0132 m_firstRun = false;
0133 }
0134 m_masterThreadState = ThreadState::BeginRun;
0135 m_masterCanProceed = true;
0136 m_mainCanProceed = false;
0137 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: Signal master for BeginRun";
0138 m_notifyMasterCv.notify_one();
0139 m_notifyMainCv.wait(lk2, [&]() { return m_mainCanProceed; });
0140
0141 lk2.unlock();
0142 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: finish BeginRun";
0143 }
0144
0145 void OscarMTMasterThread::endRun() const {
0146 std::lock_guard<std::mutex> lk(m_protectMutex);
0147 std::unique_lock<std::mutex> lk2(m_threadMutex);
0148
0149 m_masterThreadState = ThreadState::EndRun;
0150 m_mainCanProceed = false;
0151 m_masterCanProceed = true;
0152 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: Signal master for EndRun";
0153 m_notifyMasterCv.notify_one();
0154 m_notifyMainCv.wait(lk2, [&]() { return m_mainCanProceed; });
0155 lk2.unlock();
0156 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: finish EndRun";
0157 }
0158
0159 void OscarMTMasterThread::stopThread() {
0160 if (m_stopped) {
0161 return;
0162 }
0163 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread::stopTread: stop main thread";
0164 std::unique_lock<std::mutex> lk2(m_threadMutex);
0165 m_masterThreadState = ThreadState::Destruct;
0166 m_masterCanProceed = true;
0167 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread::stopTread: notify";
0168 m_notifyMasterCv.notify_one();
0169 lk2.unlock();
0170 m_masterThread.join();
0171 edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread::stopTread: is done";
0172 m_stopped = true;
0173 }