CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
OscarMTMasterThread.cc
Go to the documentation of this file.
2 
5 
10 
13 
16 
17 #include "HepPDT/ParticleDataTable.hh"
19 
20 #include "G4PhysicalVolumeStore.hh"
21 
23  m_pUseMagneticField(iConfig.getParameter<bool>("UseMagneticField")),
24  m_pDD(nullptr), m_pMF(nullptr), m_pTable(nullptr),
25  m_masterThreadState(ThreadState::NotExist),
26  m_masterCanProceed(false),
27  m_mainCanProceed(false),
28  m_firstRun(true),
29  m_stopped(false)
30 {
31  // Lock the mutex
32  std::unique_lock<std::mutex> lk(m_threadMutex);
33 
34  edm::LogInfo("SimG4CoreApplication")
35  << "OscarMTMasterThread: creating master thread";
36 
37  // Create Genat4 master thread
38  m_masterThread = std::thread([&](){
40  // Initialization
41 
42  std::shared_ptr<RunManagerMT> runManagerMaster;
43  std::unique_ptr<CustomUIsession> uiSession;
44 
45  // Lock the mutex (i.e. wait until the creating thread has called cv.wait()
46  std::unique_lock<std::mutex> lk2(m_threadMutex);
47 
48  edm::LogInfo("SimG4CoreApplication")
49  << "OscarMTMasterThread: initializing RunManagerMT";
50 
51  //UIsession manager for message handling
52  uiSession.reset(new CustomUIsession());
53 
54  // Create the master run manager, and share it to the CMSSW thread
55  runManagerMaster = std::make_shared<RunManagerMT>(iConfig);
57 
58  edm::LogInfo("SimG4CoreApplication")
59  << "OscarMTMasterThread: initialization of RunManagerMT finished";
60 
62  // State loop
63  bool isG4Alive = false;
64  while(true) {
65  // Signal main thread that it can proceed
66  m_mainCanProceed = true;
67  LogDebug("OscarMTMasterThread") << "Master thread: State loop, notify main thread";
68  m_notifyMainCv.notify_one();
69 
70  // Wait until the main thread sends signal
71  m_masterCanProceed = false;
72  LogDebug("OscarMTMasterThread") << "Master thread: State loop, starting wait";
73  m_notifyMasterCv.wait(lk2, [&]{return m_masterCanProceed;});
74 
75  // Act according to the state
76  LogDebug("OscarMTMasterThread") << "Master thread: Woke up, state is " << static_cast<int>(m_masterThreadState);
78  // Initialize Geant4
79  LogDebug("OscarMTMasterThread") << "Master thread: Initializing Geant4";
80  runManagerMaster->initG4(m_pDD, m_pMF, m_pTable);
81  isG4Alive = true;
82  }
84  // Stop Geant4
85  LogDebug("OscarMTMasterThread") << "Master thread: Stopping Geant4";
86  runManagerMaster->stopG4();
87  isG4Alive = false;
88  }
90  LogDebug("OscarMTMasterThread") << "Master thread: Breaking out of state loop";
91  if(isG4Alive)
93  << "Geant4 is still alive, master thread state must be set to EndRun before Destruct";
94  break;
95  }
96  else {
98  << "OscarMTMasterThread: Illegal master thread state "
99  << static_cast<int>(m_masterThreadState);
100  }
101  }
102 
104  // Cleanup
105  edm::LogInfo("SimG4CoreApplication")
106  << "OscarMTMasterThread: start RunManagerMT destruction";
107  LogDebug("OscarMTMasterThread")
108  << "Master thread: Am I unique owner of runManagerMaster? "
109  << runManagerMaster.unique();
110 
111  // must be done in this thread, segfault otherwise
112  runManagerMaster.reset();
113  G4PhysicalVolumeStore::Clean();
114 
115  LogDebug("OscarMTMasterThread") << "Master thread: Reseted shared_ptr";
116  lk2.unlock();
117  edm::LogInfo("SimG4CoreApplication")
118  << "OscarMTMasterThread: Master thread is finished";
119  });
120 
121  // Start waiting a signal from the condition variable (releases the lock temporarily)
122  // First for initialization
123  m_mainCanProceed = false;
124  LogDebug("OscarMTMasterThread") << "Main thread: Signal master for initialization";
125  m_notifyMainCv.wait(lk, [&](){return m_mainCanProceed;});
126 
127  lk.unlock();
128  edm::LogInfo("SimG4CoreApplication")
129  << "OscarMTMasterThread: Master thread is constructed";
130 }
131 
133  if(!m_stopped) {
134  stopThread();
135  }
136 }
137 
139  std::lock_guard<std::mutex> lk(m_protectMutex);
140 
141  std::unique_lock<std::mutex> lk2(m_threadMutex);
142 
143  // Reading from ES must be done in the main (CMSSW) thread
144  readES(iSetup);
145 
147  m_masterCanProceed = true;
148  m_mainCanProceed = false;
149  edm::LogInfo("SimG4CoreApplication")
150  << "OscarMTMasterThread: Signal master for BeginRun";
151  m_notifyMasterCv.notify_one();
152  m_notifyMainCv.wait(lk2, [&](){return m_mainCanProceed;});
153 
154  lk2.unlock();
155  edm::LogInfo("SimG4CoreApplication")
156  << "OscarMTMasterThread: finish BeginRun";
157 }
158 
160  std::lock_guard<std::mutex> lk(m_protectMutex);
161 
162  std::unique_lock<std::mutex> lk2(m_threadMutex);
164  m_mainCanProceed = false;
165  m_masterCanProceed = true;
166  edm::LogInfo("SimG4CoreApplication")
167  << "OscarMTMasterThread: Signal master for EndRun";
168  m_notifyMasterCv.notify_one();
169  m_notifyMainCv.wait(lk2, [&](){return m_mainCanProceed;});
170  lk2.unlock();
171  edm::LogInfo("SimG4CoreApplication")
172  << "OscarMTMasterThread: finish EndRun";
173 }
174 
176  if(m_stopped) {
177  return;
178  }
179  edm::LogInfo("SimG4CoreApplication")
180  << "OscarMTMasterThread::stopTread: stop main thread";
181 
182  // Release our instance of the shared master run manager, so that
183  // the G4 master thread can do the cleanup. Then notify the master
184  // thread, and join it.
185  std::unique_lock<std::mutex> lk2(m_threadMutex);
186  m_runManagerMaster.reset();
187  LogDebug("OscarMTMasterThread") << "Main thread: reseted shared_ptr";
188 
190  m_masterCanProceed = true;
191  edm::LogInfo("SimG4CoreApplication")
192  << "OscarMTMasterThread::stopTread: stop main thread";
193  m_notifyMasterCv.notify_one();
194  lk2.unlock();
195 
196  LogDebug("OscarMTMasterThread") << "Main thread: joining master thread";
197  m_masterThread.join();
198  edm::LogInfo("SimG4CoreApplication")
199  << "OscarMTMasterThread::stopTread: main thread finished";
200  m_stopped = true;
201 }
202 
203 void OscarMTMasterThread::readES(const edm::EventSetup& iSetup) const {
204  bool geomChanged = idealGeomRcdWatcher_.check(iSetup);
205  if (geomChanged && (!m_firstRun)) {
207  << "[SimG4Core OscarMTMasterThread]\n"
208  << "The Geometry configuration is changed during the job execution\n"
209  << "this is not allowed, the geometry must stay unchanged";
210  }
211  if (m_pUseMagneticField) {
212  bool magChanged = idealMagRcdWatcher_.check(iSetup);
213  if (magChanged && (!m_firstRun)) {
215  << "[SimG4Core OscarMTMasterThread]\n"
216  << "The MagneticField configuration is changed during the job execution\n"
217  << "this is not allowed, the MagneticField must stay unchanged";
218  }
219  }
220  // Don't read from ES if not the first run, just as in
221  if(!m_firstRun)
222  return;
223 
224  // DDDWorld: get the DDCV from the ES and use it to build the World
226  iSetup.get<IdealGeometryRecord>().get(pDD);
227  m_pDD = pDD.product();
228 
229  if(m_pUseMagneticField) {
231  iSetup.get<IdealMagneticFieldRecord>().get(pMF);
232  m_pMF = pMF.product();
233  }
234 
236  iSetup.get<PDTRecord>().get(fTable);
237  m_pTable = fTable.product();
238 
239  m_firstRun = false;
240 }
#define LogDebug(id)
std::shared_ptr< RunManagerMT > m_runManagerMaster
edm::ESWatcher< IdealGeometryRecord > idealGeomRcdWatcher_
#define nullptr
const RunManagerMT & runManagerMaster() const
ThreadState m_masterThreadState
void beginRun(const edm::EventSetup &iSetup) const
std::condition_variable m_notifyMasterCv
void readES(const edm::EventSetup &iSetup) const
const DDCompactView * m_pDD
const T & get() const
Definition: EventSetup.h:56
T const * product() const
Definition: ESHandle.h:86
OscarMTMasterThread(const edm::ParameterSet &iConfig)
T const * product() const
bool check(const edm::EventSetup &iSetup)
Definition: ESWatcher.h:57
edm::ESWatcher< IdealMagneticFieldRecord > idealMagRcdWatcher_
volatile std::atomic< bool > shutdown_flag false
const MagneticField * m_pMF
const HepPDT::ParticleDataTable * m_pTable
std::condition_variable m_notifyMainCv