CMS 3D CMS Logo

OscarMTMasterThread.cc
Go to the documentation of this file.
1 #include <memory>
2 
6 
9 
10 #include "G4PhysicalVolumeStore.hh"
11 
13  : m_pGeoFromDD4hep(iConfig.getParameter<bool>("g4GeometryDD4hepSource")),
14  m_masterThreadState(ThreadState::NotExist) {
15  // Lock the mutex
16  std::unique_lock<std::mutex> lk(m_threadMutex);
17 
18  edm::LogVerbatim("SimG4CoreApplication")
19  << "OscarMTMasterThread: creating master thread DD4hep: " << m_pGeoFromDD4hep;
20 
21  // Create Geant4 master thread
22  m_masterThread = std::thread([&]() {
24  // Initialization
25  std::unique_ptr<CustomUIsession> uiSession;
26 
27  // Lock the mutex (i.e. wait until the creating thread has called cv.wait()
28  std::unique_lock<std::mutex> lk2(m_threadMutex);
29 
30  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: initializing RunManagerMT";
31 
32  //UIsession manager for message handling
33  uiSession = std::make_unique<CustomUIsession>();
34 
35  // Create the master run manager, and share it to the CMSSW thread
36  m_runManagerMaster = std::make_shared<RunManagerMT>(iConfig);
37 
39  // State loop
40  bool isG4Alive = false;
41  while (true) {
42  // Signal main thread that it can proceed
43  m_mainCanProceed = true;
44  edm::LogVerbatim("OscarMTMasterThread") << "Master thread: State loop, notify main thread";
45  m_notifyMainCv.notify_one();
46 
47  // Wait until the main thread sends signal
48  m_masterCanProceed = false;
49  edm::LogVerbatim("OscarMTMasterThread") << "Master thread: State loop, starting wait";
50  m_notifyMasterCv.wait(lk2, [&] { return m_masterCanProceed; });
51  //m_notifyMasterCv.wait(lk2, [&] { return false; });
52 
53  // Act according to the state
54  edm::LogVerbatim("OscarMTMasterThread")
55  << "Master thread: Woke up, state is " << static_cast<int>(m_masterThreadState);
57  // Initialize Geant4
58  edm::LogVerbatim("OscarMTMasterThread") << "Master thread: Initializing Geant4";
60  isG4Alive = true;
62  // Stop Geant4
63  edm::LogVerbatim("OscarMTMasterThread") << "Master thread: Stopping Geant4";
64  m_runManagerMaster->stopG4();
65  isG4Alive = false;
67  edm::LogVerbatim("OscarMTMasterThread") << "Master thread: Breaking out of state loop";
68  if (isG4Alive)
69  throw cms::Exception("LogicError") << "OscarMTMasterThread: Geant4 is still alive, master thread "
70  << "state must be set to EndRun before Destruct";
71  break;
72  } else {
73  throw cms::Exception("LogicError")
74  << "OscarMTMasterThread: Illegal master thread state " << static_cast<int>(m_masterThreadState);
75  }
76  }
77 
79  // Cleanup
80  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: start RunManagerMT destruction";
81 
82  // must be done in this thread, segfault otherwise
83  m_runManagerMaster.reset();
84  G4PhysicalVolumeStore::Clean();
85 
86  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: physics and geometry are cleaned";
87  lk2.unlock();
88  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: Master thread is finished";
89  });
90 
91  // Start waiting a signal from the condition variable (releases the lock temporarily)
92  // First for initialization
93  m_mainCanProceed = false;
94  LogDebug("OscarMTMasterThread") << "Main thread: Signal master for initialization";
95  m_notifyMainCv.wait(lk, [&]() { return m_mainCanProceed; });
96 
97  lk.unlock();
98  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: Master thread is constructed";
99 }
100 
102  if (!m_stopped) {
103  stopThread();
104  }
105 }
106 
108  if (m_hasToken) {
109  return;
110  }
111  if (m_pGeoFromDD4hep) {
113  } else {
115  }
117  m_hasToken = true;
118 }
119 
121  std::lock_guard<std::mutex> lk(m_protectMutex);
122  std::unique_lock<std::mutex> lk2(m_threadMutex);
123  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread::beginRun";
124 
125  if (m_firstRun) {
126  if (m_pGeoFromDD4hep) {
127  m_pDD4hep = &(*iSetup.getTransientHandle(m_DD4hep));
128  } else {
129  m_pDDD = &(*iSetup.getTransientHandle(m_DDD));
130  }
131  m_pTable = &iSetup.getData(m_PDT);
132  m_firstRun = false;
133  }
135  m_masterCanProceed = true;
136  m_mainCanProceed = false;
137  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: Signal master for BeginRun";
138  m_notifyMasterCv.notify_one();
139  m_notifyMainCv.wait(lk2, [&]() { return m_mainCanProceed; });
140 
141  lk2.unlock();
142  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: finish BeginRun";
143 }
144 
146  std::lock_guard<std::mutex> lk(m_protectMutex);
147  std::unique_lock<std::mutex> lk2(m_threadMutex);
148 
150  m_mainCanProceed = false;
151  m_masterCanProceed = true;
152  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: Signal master for EndRun";
153  m_notifyMasterCv.notify_one();
154  m_notifyMainCv.wait(lk2, [&]() { return m_mainCanProceed; });
155  lk2.unlock();
156  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread: finish EndRun";
157 }
158 
160  if (m_stopped) {
161  return;
162  }
163  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread::stopTread: stop main thread";
164  std::unique_lock<std::mutex> lk2(m_threadMutex);
166  m_masterCanProceed = true;
167  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread::stopTread: notify";
168  m_notifyMasterCv.notify_one();
169  lk2.unlock();
170  m_masterThread.join();
171  edm::LogVerbatim("SimG4CoreApplication") << "OscarMTMasterThread::stopTread: is done";
172  m_stopped = true;
173 }
Log< level::Info, true > LogVerbatim
T const & getData(const ESGetToken< T, R > &iToken) const noexcept(false)
Definition: EventSetup.h:119
HepPDT::ParticleDataTable ParticleDataTable
std::shared_ptr< RunManagerMT > m_runManagerMaster
edm::ESGetToken< cms::DDCompactView, IdealGeometryRecord > m_DD4hep
void beginRun(const edm::EventSetup &iSetup) const
edm::ESGetToken< DDCompactView, IdealGeometryRecord > m_DDD
Compact representation of the geometrical detector hierarchy.
Definition: DDCompactView.h:81
ThreadState m_masterThreadState
const cms::DDCompactView * m_pDD4hep
std::condition_variable m_notifyMasterCv
OscarMTMasterThread(const edm::ParameterSet &iConfig)
edm::ESGetToken< HepPDT::ParticleDataTable, PDTRecord > m_PDT
const DDCompactView * m_pDDD
void callConsumes(edm::ConsumesCollector &&iC) const
ESTransientHandle< T > getTransientHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:141
const HepPDT::ParticleDataTable * m_pTable
std::condition_variable m_notifyMainCv
#define LogDebug(id)