test
CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
RunManagerMTWorker.cc
Go to the documentation of this file.
13 
20 
27 
33 
38 
40 
42 
44 
45 #include "G4Event.hh"
46 #include "G4Run.hh"
47 #include "G4SystemOfUnits.hh"
48 #include "G4Threading.hh"
49 #include "G4UImanager.hh"
50 #include "G4WorkerThread.hh"
51 #include "G4WorkerRunManagerKernel.hh"
52 #include "G4StateManager.hh"
53 #include "G4TransportationManager.hh"
54 
55 #include <atomic>
56 #include <thread>
57 #include <sstream>
58 #include <vector>
59 
60 // from https://hypernews.cern.ch/HyperNews/CMS/get/edmFramework/3302/2.html
61 namespace {
62  static std::atomic<int> thread_counter{ 0 };
63 
64  int get_new_thread_index() {
65  return thread_counter++;
66  }
67 
68  static thread_local int s_thread_index = get_new_thread_index();
69 
70  int getThreadIndex() { return s_thread_index; }
71 
72  void createWatchers(const edm::ParameterSet& iP,
73  SimActivityRegistry& iReg,
74  std::vector<std::shared_ptr<SimWatcher> >& oWatchers,
75  std::vector<std::shared_ptr<SimProducer> >& oProds,
76  int thisThreadID
77  )
78  {
79  using namespace std;
80  using namespace edm;
81  if(!iP.exists("Watchers")) { return; }
82 
83  vector<ParameterSet> watchers = iP.getParameter<vector<ParameterSet> >("Watchers");
84 
85  if(thisThreadID > 0) {
86  throw edm::Exception(edm::errors::Configuration) << "SimWatchers are not supported for more than 1 thread. If this use case is needed, RunManagerMTWorker has to be updated, and SimWatchers and SimProducers have to be made thread safe.";
87  }
88 
89  for(vector<ParameterSet>::iterator itWatcher = watchers.begin();
90  itWatcher != watchers.end();
91  ++itWatcher) {
92  std::unique_ptr<SimWatcherMakerBase> maker(
93  SimWatcherFactory::get()->create(itWatcher->getParameter<std::string>("type"))
94  );
95  if(maker.get()==nullptr) {
97  << "Unable to find the requested Watcher";
98  }
99 
100  std::shared_ptr<SimWatcher> watcherTemp;
101  std::shared_ptr<SimProducer> producerTemp;
102  maker->make(*itWatcher,iReg,watcherTemp,producerTemp);
103  oWatchers.push_back(watcherTemp);
104  if(producerTemp) {
105  oProds.push_back(producerTemp);
106  }
107  }
108  }
109 }
110 
112  std::unique_ptr<CustomUIsession> UIsession;
113  std::unique_ptr<RunAction> userRunAction;
114  std::unique_ptr<SimRunInterface> runInterface;
116  std::unique_ptr<SimTrackManager> trackManager;
117  std::vector<SensitiveTkDetector*> sensTkDets;
118  std::vector<SensitiveCaloDetector*> sensCaloDets;
119  std::vector<std::shared_ptr<SimWatcher> > watchers;
120  std::vector<std::shared_ptr<SimProducer> > producers;
121  std::unique_ptr<sim::FieldBuilder> fieldBuilder;
122  std::unique_ptr<G4Run> currentRun;
123  std::unique_ptr<G4Event> currentEvent;
125  G4RunManagerKernel* kernel = nullptr;
126  bool threadInitialized = false;
127  bool runTerminated = false;
128 };
129 
131 
133  m_generator(iConfig.getParameter<edm::ParameterSet>("Generator")),
134  m_InToken(iC.consumes<edm::HepMCProduct>(iConfig.getParameter<edm::ParameterSet>("Generator").getParameter<std::string>("HepMCProductLabel"))),
135  m_theLHCTlinkToken(iC.consumes<edm::LHCTransportLinkContainer>(iConfig.getParameter<edm::InputTag>("theLHCTlinkTag"))),
136  m_nonBeam(iConfig.getParameter<bool>("NonBeamEvent")),
137  m_pUseMagneticField(iConfig.getParameter<bool>("UseMagneticField")),
138  m_EvtMgrVerbosity(iConfig.getUntrackedParameter<int>("G4EventManagerVerbosity",0)),
139  m_pField(iConfig.getParameter<edm::ParameterSet>("MagneticField")),
140  m_pRunAction(iConfig.getParameter<edm::ParameterSet>("RunAction")),
141  m_pEventAction(iConfig.getParameter<edm::ParameterSet>("EventAction")),
142  m_pStackingAction(iConfig.getParameter<edm::ParameterSet>("StackingAction")),
143  m_pTrackingAction(iConfig.getParameter<edm::ParameterSet>("TrackingAction")),
144  m_pSteppingAction(iConfig.getParameter<edm::ParameterSet>("SteppingAction")),
145  m_pCustomUIsession(iConfig.getUntrackedParameter<edm::ParameterSet>("CustomUIsession")),
146  m_p(iConfig)
147 {
148  initializeTLS();
149  m_sVerbose.reset(nullptr);
150  std::vector<edm::ParameterSet> watchers =
151  iConfig.getParameter<std::vector<edm::ParameterSet> >("Watchers");
152  m_hasWatchers = (watchers.empty()) ? false : true;
153 }
154 
156  if(m_tls && !m_tls->runTerminated) { terminateRun(); }
157 }
158 
160  terminateRun();
161 }
162 
164  if(m_tls) { return; }
165  m_tls = new TLSData;
166 
167  edm::Service<SimActivityRegistry> otherRegistry;
168  //Look for an outside SimActivityRegistry
169  // this is used by the visualization code
170  int thisID = getThreadIndex();
171  if(otherRegistry){
172  m_tls->registry.connect(*otherRegistry);
173  if(thisID > 0) {
174  throw edm::Exception(edm::errors::Configuration) << "SimActivityRegistry service (i.e. visualization) is not supported for more than 1 thread. If this use case is needed, RunManagerMTWorker has to be updated.";
175  }
176  }
177  if(m_hasWatchers) {
179  }
180 }
181 
183  // I guess everything initialized here should be in thread_local storage
184  initializeTLS();
185 
186  int thisID = getThreadIndex();
187 
188  edm::LogInfo("SimG4CoreApplication")
189  << "RunManagerMTWorker::initializeThread " << thisID;
190 
191  // Initialize per-thread output
192  G4Threading::G4SetThreadId( thisID );
193  G4UImanager::GetUIpointer()->SetUpForAThread( thisID );
195  if(uitype == "MessageLogger") {
196  m_tls->UIsession.reset(new CustomUIsession());
197  }
198  else if(uitype == "MessageLoggerThreadPrefix") {
200  }
201  else if(uitype == "FilePerThread") {
203  }
204  else {
206  << "Invalid value of CustomUIsession.Type '" << uitype
207  << "', valid are MessageLogger, MessageLoggerThreadPrefix, FilePerThread";
208  }
209 
210  // Initialize worker part of shared resources (geometry, physics)
211  G4WorkerThread::BuildGeometryAndPhysicsVector();
212 
213  // Create worker run manager
214  m_tls->kernel = G4WorkerRunManagerKernel::GetRunManagerKernel();
215  if(!m_tls->kernel) { m_tls->kernel = new G4WorkerRunManagerKernel(); }
216 
217  // Set the geometry for the worker, share from master
219 
220  // we need the track manager now
221  m_tls->trackManager.reset(new SimTrackManager());
222 
223  // Get DDCompactView, or would it be better to get the object from
224  // runManagerMaster instead of EventSetup in here?
226  es.get<IdealGeometryRecord>().get(pDD);
227 
228  // setup the magnetic field
230  {
231  const GlobalPoint g(0.,0.,0.);
232 
234  es.get<IdealMagneticFieldRecord>().get(pMF);
235 
237  G4TransportationManager * tM =
238  G4TransportationManager::GetTransportationManager();
239  m_tls->fieldBuilder->build( tM->GetFieldManager(),
240  tM->GetPropagatorInField(),
241  runManagerMaster.chordFinderSetterForWorker());
242  }
243 
244 
245  // attach sensitive detector
246  AttachSD attach;
247  std::pair< std::vector<SensitiveTkDetector*>,
248  std::vector<SensitiveCaloDetector*> > sensDets =
249  attach.create(runManagerMaster.world(),
250  (*pDD),
251  runManagerMaster.catalog(),
252  m_p,
253  m_tls->trackManager.get(),
254  m_tls->registry);
255 
256  m_tls->sensTkDets.swap(sensDets.first);
257  m_tls->sensCaloDets.swap(sensDets.second);
258 
259  edm::LogInfo("SimG4CoreApplication")
260  << " RunManagerMTWorker: Sensitive Detector "
261  << "building finished; found "
262  << m_tls->sensTkDets.size()
263  << " Tk type Producers, and "
264  << m_tls->sensCaloDets.size()
265  << " Calo type producers ";
266 
267  // Set the physics list for the worker, share from master
268  PhysicsList *physicsList = runManagerMaster.physicsListForWorker();
269 
270  edm::LogInfo("SimG4CoreApplication")
271  << "RunManagerMTWorker: start initialisation of PhysicsList for a thread";
272 
273  physicsList->InitializeWorker();
274  m_tls->kernel->SetPhysics(physicsList);
275  m_tls->kernel->InitializePhysics();
276 
277  const bool kernelInit = m_tls->kernel->RunInitialization();
278  if(!kernelInit) {
279  throw SimG4Exception("G4WorkerRunManagerKernel initialization failed");
280  }
281  //tell all interesting parties that we are beginning the job
282  BeginOfJob aBeginOfJob(&es);
283  m_tls->registry.beginOfJobSignal_(&aBeginOfJob);
284 
285  G4int sv = m_p.getParameter<int>("SteppingVerbosity");
286  G4double elim = m_p.getParameter<double>("StepVerboseThreshold")*CLHEP::GeV;
287  std::vector<int> ve = m_p.getParameter<std::vector<int> >("VerboseEvents");
288  std::vector<int> vn = m_p.getParameter<std::vector<int> >("VertexNumber");
289  std::vector<int> vt = m_p.getParameter<std::vector<int> >("VerboseTracks");
290 
291  if(sv > 0) {
292  m_sVerbose.reset(new CMSSteppingVerbose(sv, elim, ve, vn, vt));
293  }
295 
296  edm::LogInfo("SimG4CoreApplication")
297  << "RunManagerMTWorker::initializeThread done for the thread " << thisID;
298 
299  for(const std::string& command: runManagerMaster.G4Commands()) {
300  edm::LogInfo("SimG4CoreApplication") << "RunManagerMTWorker:: Requests UI: "
301  << command;
302  G4UImanager::GetUIpointer()->ApplyCommand(command);
303  }
304 }
305 
307  m_tls->runInterface.reset(new SimRunInterface(this, false));
309  m_tls->runInterface.get(),false));
310  m_tls->userRunAction->SetMaster(false);
311  Connect(m_tls->userRunAction.get());
312 
313  G4EventManager * eventManager = m_tls->kernel->GetEventManager();
314  eventManager->SetVerboseLevel(m_EvtMgrVerbosity);
315 
316  EventAction * userEventAction =
318  m_tls->trackManager.get(), m_sVerbose.get());
319  Connect(userEventAction);
320  eventManager->SetUserAction(userEventAction);
321 
322  TrackingAction* userTrackingAction =
323  new TrackingAction(userEventAction, m_pTrackingAction, m_sVerbose.get());
324  Connect(userTrackingAction);
325  eventManager->SetUserAction(userTrackingAction);
326 
327  SteppingAction* userSteppingAction =
328  new SteppingAction(userEventAction,m_pSteppingAction,m_sVerbose.get(),m_hasWatchers);
329  Connect(userSteppingAction);
330  eventManager->SetUserAction(userSteppingAction);
331 
332  eventManager->SetUserAction(new StackingAction(userTrackingAction,
334 
335 }
336 
338 {
341 }
342 
344 {
347 }
348 
350 {
353 }
354 
356 {
358 }
359 
361  initializeTLS();
362  return m_tls->trackManager.get();
363 }
364 std::vector<SensitiveTkDetector*>& RunManagerMTWorker::sensTkDetectors() {
365  initializeTLS();
366  return m_tls->sensTkDets;
367 }
368 std::vector<SensitiveCaloDetector*>& RunManagerMTWorker::sensCaloDetectors() {
369  initializeTLS();
370  return m_tls->sensCaloDets;
371 }
372 std::vector<std::shared_ptr<SimProducer> > RunManagerMTWorker::producers() {
373  initializeTLS();
374  return m_tls->producers;
375 }
376 
378  m_tls->currentRun.reset(new G4Run());
379  G4StateManager::GetStateManager()->SetNewState(G4State_GeomClosed);
380  if (m_tls->userRunAction) { m_tls->userRunAction->BeginOfRunAction(m_tls->currentRun.get()); }
381 }
382 
384  if(!m_tls || m_tls->runTerminated) { return; }
385  if(m_tls->userRunAction) {
386  m_tls->userRunAction->EndOfRunAction(m_tls->currentRun.get());
387  m_tls->userRunAction.reset();
388  }
389  m_tls->currentEvent.reset();
390  m_simEvent.reset();
391 
392  if(m_tls->kernel) {
393  m_tls->kernel->RunTermination();
394  }
395 
396  m_tls->runTerminated = true;
397 }
398 
400  RunManagerMT& runManagerMaster) {
401  // The initialization and begin/end run is a bit convoluted due to
402  // - Geant4 deals per-thread
403  // - OscarMTProducer deals per-stream
404  // and framework/TBB is free to schedule work in streams to the
405  // threads as it likes.
406  //
407  // We have to do the per-thread initialization, and per-thread
408  // per-run initialization here by ourselves.
409 
410  if(!(m_tls && m_tls->threadInitialized)) {
411  LogDebug("SimG4CoreApplication")
412  << "RunManagerMTWorker::produce(): stream "
413  << inpevt.streamID() << " thread " << getThreadIndex() << " initializing";
414  initializeThread(runManagerMaster, es);
415  m_tls->threadInitialized = true;
416  }
417  // Initialize run
418  if(inpevt.id().run() != m_tls->currentRunNumber) {
419  if(m_tls->currentRunNumber != 0 && !m_tls->runTerminated) {
420  // If previous run in this thread was not terminated via endRun() call, terminate it now
421  terminateRun();
422  }
423  initializeRun();
424  m_tls->currentRunNumber = inpevt.id().run();
425  }
426  m_tls->runInterface->setRunManagerMTWorker(this); // For UserActions
427 
428  m_tls->currentEvent.reset(generateEvent(inpevt));
429 
430  m_simEvent.reset(new G4SimEvent());
431  m_simEvent->hepEvent(m_generator.genEvent());
433  if (m_generator.genVertex() != nullptr ) {
434  auto genVertex = m_generator.genVertex();
435  m_simEvent->collisionPoint(
436  math::XYZTLorentzVectorD(genVertex->x()/centimeter,
437  genVertex->y()/centimeter,
438  genVertex->z()/centimeter,
439  genVertex->t()/second));
440  }
441  if (m_tls->currentEvent->GetNumberOfPrimaryVertex()==0) {
442  std::stringstream ss;
443  ss << "RunManagerMTWorker::produce(): event " << inpevt.id().event()
444  << " with no G4PrimaryVertices \n" ;
445  throw SimG4Exception(ss.str());
446 
447  } else {
448  if(!m_tls->kernel) {
449  std::stringstream ss;
450  ss << " RunManagerMT::produce(): "
451  << " no G4WorkerRunManagerKernel yet for thread index"
452  << getThreadIndex() << ", id " << std::hex
453  << std::this_thread::get_id() << " \n";
454  throw SimG4Exception(ss.str());
455  }
456 
457  edm::LogInfo("SimG4CoreApplication")
458  << " RunManagerMTWorker::produce: start Event " << inpevt.id().event()
459  << " stream id " << inpevt.streamID()
460  << " thread index " << getThreadIndex()
461  << " of weight " << m_simEvent->weight()
462  << " with " << m_simEvent->nTracks() << " tracks and "
463  << m_simEvent->nVertices()
464  << " vertices, generated by " << m_simEvent->nGenParts() << " particles ";
465 
466  m_tls->kernel->GetEventManager()->ProcessOneEvent(m_tls->currentEvent.get());
467 
468  edm::LogInfo("SimG4CoreApplication")
469  << " RunManagerMTWorker::produce: ended Event " << inpevt.id().event();
470  }
471 }
472 
474  if(m_tls->runTerminated) { return; }
475  G4Track* t = m_tls->kernel->GetEventManager()->GetTrackingManager()->GetTrack();
476  t->SetTrackStatus(fStopAndKill) ;
477 
478  // CMS-specific act
479  //
480  TrackingAction* uta =
481  static_cast<TrackingAction *>(m_tls->kernel->GetEventManager()->GetUserTrackingAction());
482  uta->PostUserTrackingAction(t) ;
483 
484  m_tls->currentEvent->SetEventAborted();
485  m_tls->kernel->GetEventManager()->GetStackManager()->clear();
486  m_tls->kernel->GetEventManager()->GetTrackingManager()->EventAborted();
487 }
488 
489 void RunManagerMTWorker::abortRun(bool softAbort) {
490  if (!softAbort) { abortEvent(); }
491  m_tls->currentRun.reset();
492  terminateRun();
493 }
494 
496  m_tls->currentEvent.reset();
497  m_simEvent.reset();
498 
499  // 64 bits event ID in CMSSW converted into Geant4 event ID
500  G4int evtid = (G4int)inpevt.id().event();
501  G4Event * evt = new G4Event(evtid);
502 
504 
505  inpevt.getByToken(m_InToken, HepMCEvt);
506 
507  m_generator.setGenEvent(HepMCEvt->GetEvent());
508 
509  // required to reset the GenParticle Id for particles transported
510  // along the beam pipe
511  // to their original value for SimTrack creation
512  resetGenParticleId( inpevt );
513 
514  if (!m_nonBeam)
515  {
516  m_generator.HepMC2G4(HepMCEvt->GetEvent(),evt);
517  }
518  else
519  {
520  m_generator.nonBeamEvent2G4(HepMCEvt->GetEvent(),evt);
521  }
522 
523  return evt;
524 }
525 
527 {
529  inpevt.getByToken( m_theLHCTlinkToken, theLHCTlink );
530  if ( theLHCTlink.isValid() ) {
531  m_tls->trackManager->setLHCTransportLink( theLHCTlink.product() );
532  }
533 }
#define LogDebug(id)
RunNumber_t run() const
Definition: EventID.h:39
edm::ParameterSet m_pSteppingAction
T getParameter(std::string const &) const
EventNumber_t event() const
Definition: EventID.h:41
std::vector< std::shared_ptr< SimWatcher > > watchers
const SensitiveDetectorCatalog & catalog() const
Definition: RunManagerMT.h:84
T getUntrackedParameter(std::string const &, T const &) const
virtual const math::XYZTLorentzVector * genVertex() const
Definition: Generator.h:30
const double GeV
Definition: MathUtil.h:16
std::unique_ptr< G4Event > currentEvent
virtual const double eventWeight() const
Definition: Generator.h:31
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > XYZTLorentzVectorD
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:14
virtual const HepMC::GenEvent * genEvent() const
Definition: Generator.h:29
SimActivityRegistry::G4StepSignal m_g4StepSignal
SimTrackManager * GetSimTrackManager()
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:457
void connect(Observer< const BeginOfJob * > *iObject)
void HepMC2G4(const HepMC::GenEvent *g, G4Event *e)
Definition: Generator.cc:100
EndOfEventSignal endOfEventSignal_
std::unique_ptr< SimRunInterface > runInterface
std::unique_ptr< CMSSteppingVerbose > m_sVerbose
SimActivityRegistry::EndOfRunSignal m_endOfRunSignal
Definition: RunAction.h:26
bool exists(std::string const &parameterName) const
checks if a parameter exists
BeginOfRunSignal beginOfRunSignal_
std::vector< SensitiveTkDetector * > sensTkDets
std::unique_ptr< sim::FieldBuilder > fieldBuilder
SimActivityRegistry::EndOfEventSignal m_endOfEventSignal
Definition: EventAction.h:54
static void createWatchers(const edm::ParameterSet &iP, SimActivityRegistry &iReg, std::vector< std::shared_ptr< SimWatcher > > &oWatchers, std::vector< std::shared_ptr< SimProducer > > &oProds)
Definition: RunManager.cc:82
#define nullptr
edm::EDGetTokenT< edm::HepMCProduct > m_InToken
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
BeginOfJobSignal beginOfJobSignal_
U second(std::pair< T, U > const &p)
edm::ParameterSet m_pEventAction
const DDDWorld & world() const
Definition: RunManagerMT.h:80
std::unique_ptr< SimTrackManager > trackManager
std::unique_ptr< CustomUIsession > UIsession
std::unique_ptr< G4SimEvent > m_simEvent
static thread_local TLSData * m_tls
edm::ParameterSet m_pRunAction
std::vector< SensitiveCaloDetector * > sensCaloDets
std::vector< SensitiveTkDetector * > & sensTkDetectors()
void resetGenParticleId(const edm::Event &inpevt)
std::unique_ptr< RunAction > userRunAction
void initializeThread(RunManagerMT &runManagerMaster, const edm::EventSetup &es)
void setGenEvent(const HepMC::GenEvent *inpevt)
Definition: Generator.h:25
BeginOfEventSignal beginOfEventSignal_
sim::ChordFinderSetter * chordFinderSetterForWorker() const
Definition: RunManagerMT.h:103
SimActivityRegistry::EndOfTrackSignal m_endOfTrackSignal
bool isValid() const
Definition: HandleBase.h:75
EndOfRunSignal endOfRunSignal_
std::vector< std::shared_ptr< SimProducer > > producers
void abortRun(bool softAbort=false)
RunManagerMTWorker(const edm::ParameterSet &iConfig, edm::ConsumesCollector &&i)
void connect(Observer< const T * > *iObs)
does not take ownership of memory
Definition: Signaler.h:59
PhysicsList * physicsListForWorker() const
Definition: RunManagerMT.h:95
T const * product() const
Definition: Handle.h:81
virtual void PostUserTrackingAction(const G4Track *aTrack)
std::vector< SensitiveCaloDetector * > & sensCaloDetectors()
edm::ParameterSet m_pTrackingAction
void produce(const edm::Event &inpevt, const edm::EventSetup &es, RunManagerMT &runManagerMaster)
std::unique_ptr< G4Run > currentRun
edm::ParameterSet m_pField
const T & get() const
Definition: EventSetup.h:56
T const * product() const
Definition: ESHandle.h:86
std::pair< std::vector< SensitiveTkDetector * >, std::vector< SensitiveCaloDetector * > > create(const DDDWorld &w, const DDCompactView &cpv, const SensitiveDetectorCatalog &clg, edm::ParameterSet const &p, const SimTrackManager *m, SimActivityRegistry &reg) const
Definition: AttachSD.cc:23
G4VPhysicalVolume * GetWorldVolumeForWorker() const
Definition: DDDWorld.h:24
G4Event * generateEvent(const edm::Event &inpevt)
string command
Definition: mps_check.py:26
edm::EDGetTokenT< edm::LHCTransportLinkContainer > m_theLHCTlinkToken
void nonBeamEvent2G4(const HepMC::GenEvent *g, G4Event *e)
Definition: Generator.cc:529
static void WorkerSetAsWorld(G4VPhysicalVolume *pv)
Definition: DDDWorld.cc:38
SimActivityRegistry::BeginOfRunSignal m_beginOfRunSignal
Definition: RunAction.h:25
const std::vector< std::string > & G4Commands() const
Definition: RunManagerMT.h:88
edm::EventID id() const
Definition: EventBase.h:58
edm::ParameterSet m_pCustomUIsession
std::vector< std::shared_ptr< SimProducer > > producers()
StreamID streamID() const
Definition: Event.h:81
std::vector< LHCTransportLink > LHCTransportLinkContainer
unsigned int RunNumber_t
EndOfTrackSignal endOfTrackSignal_
edm::ParameterSet m_p
SimActivityRegistry::BeginOfEventSignal m_beginOfEventSignal
Definition: EventAction.h:53
T get(const Candidate &c)
Definition: component.h:55
BeginOfTrackSignal beginOfTrackSignal_
edm::ParameterSet m_pStackingAction
void Connect(RunAction *)
SimActivityRegistry::BeginOfTrackSignal m_beginOfTrackSignal