Geant4  10.00.p01
G4MTRunManager.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 
28 #include "G4MTRunManager.hh"
29 #include "G4MTRunManagerKernel.hh"
30 #include "G4Timer.hh"
31 #include "G4StateManager.hh"
32 #include "G4ScoringManager.hh"
37 #include "G4WorkerThread.hh"
38 #include "G4Run.hh"
39 #include "G4UImanager.hh"
40 #include "G4AutoLock.hh"
41 #include "G4WorkerRunManager.hh"
42 #include "G4UserRunAction.hh"
43 #include "G4ProductionCutsTable.hh"
44 #include "G4Timer.hh"
45 
49 
50 namespace {
51  G4Mutex cmdHandlingMutex = G4MUTEX_INITIALIZER;
52  G4Mutex scorerMergerMutex = G4MUTEX_INITIALIZER;
53  G4Mutex runMergerMutex = G4MUTEX_INITIALIZER;
54  G4Mutex setUpEventMutex = G4MUTEX_INITIALIZER;
55 }
56 
57 //This is needed to initialize windows conditions
58 #if defined(WIN32)
59 namespace {
60  void InitializeWindowsConditions();
61 }
62 #endif
63 
65 {
67  return fMasterRM;
71 }
72 
74 {
75  return fMasterRM->kernel;
76 }
77 
79 {
80  return fMasterRM->MTkernel;
81 }
82 
84  nworkers(2),forcedNwokers(-1),
85  masterRNGEngine(0),
86  nextActionRequest(UNDEFINED),
87  eventModuloDef(0),eventModulo(1),
88  nSeedsUsed(0),nSeedsFilled(0),
89  nSeedsMax(10000),nSeedsPerEvent(2)
90 {
91  if ( fMasterRM )
92  {
93  G4Exception("G4MTRunManager::G4MTRunManager", "Run0035",FatalException,
94  "Another instance of a G4MTRunManager already exists.");
95  }
96  fMasterRM = this;
97  MTkernel = static_cast<G4MTRunManagerKernel*>(kernel);
98 #ifndef G4MULTITHREADED
100  msg << "Geant4 code is compiled without multi-threading support"
101  << "(-DG4MULTITHREADED is set to off).\n";
102  msg << "G4MTRunManager can only be used in multi-threaded applications.";
103  G4Exception("G4MTRunManager::G4MTRunManager","Run0035",FatalException,msg);
104 #endif
105 
106  G4int numberOfStaticAllocators = kernel->GetNumberOfStaticAllocators();
107  if(numberOfStaticAllocators>0)
108  {
110  msg1 << "There are " << numberOfStaticAllocators
111  << " static G4Allocator objects detected.\n"
112  << "In multi-threaded mode, all G4Allocator objects must be dynamicly instantiated.";
113  G4Exception("G4MTRunManager::G4MTRunManager","Run1035",FatalException,msg1);
114  }
117 
118  //Check if a default RandomNumberGenerator has been created by user,
119  // if not create default one
120  //Note this call forces creation of defaults if not already there
121  //G4Random::getTheEngine(); //User did not specify RNG, create defaults
122  //Now remember the master instance of the RNG Engine
123  masterRNGEngine = G4Random::getTheEngine();
124 #if defined (WIN32)
125  InitializeWindowsConditions();
126 #endif
127 
129  randDbl = new double[nSeedsPerEvent*nSeedsMax];
130 
131  char* env = getenv("G4FORCENUMBEROFTHREADS");
132  if(env)
133  {
134  G4String envS = env;
135  if(envS=="MAX"||envS=="max")
137  else
138  {
139  std::istringstream is(env);
140  G4int val = -1;
141  is >> val;
142  if(val>0)
143  { forcedNwokers = val; }
144  else
145  {
147  msg2 << "Environment variable G4FORCENUMBEROFTHREADS has an invalid value <"
148  << envS << ">. It has to be an integer or a word \"max\".\n"
149  << "G4FORCENUMBEROFTHREADS is ignored.";
150  G4Exception("G4MTRunManager::G4MTRunManager","Run1039",JustWarning,msg2);
151  }
152  }
153  if(forcedNwokers>0)
154  {
156  G4cout << "### Number of threads is forced to " << forcedNwokers
157  << " by Environment variable G4FORCENUMBEROFTHREADS." << G4endl;
158  }
159  }
160 }
161 
163 {
164  //TODO: Currently does not work due to concurrent deletion of something
165  // that is shared:
166  //G4ProcessTable::DeleteMessenger from ~G4RunManager
167  //G4cout<<"Destroy MTRunManager"<<G4endl;//ANDREA
169  delete [] randDbl;
170 }
171 
173 {
174  std::ostringstream os;
175  os << randomNumberStatusDir << "G4Master_"<<fn <<".rndm";
176  G4Random::saveEngineStatus(os.str().c_str());
177 }
178 
180 {
181  if ( threads.size() != 0 )
182  {
184  msg << "Number of threads cannot be changed at this moment \n"
185  << "(old threads are still alive). Method ignored.";
186  G4Exception("G4MTRunManager::SetNumberOfThreads(G4int)",
187  "Run0035", JustWarning, msg);
188  }
189  else if ( forcedNwokers > 0 )
190  {
192  msg << "Number of threads is forced to " << forcedNwokers
193  << " by G4FORCENUMBEROFWORKERS shell variable.\n"
194  << "Method ignored.";
195  G4Exception("G4MTRunManager::SetNumberOfThreads(G4int)",
196  "Run0035", JustWarning, msg);
197  }
198  else
199  {
200  nworkers = n;
201  }
202 }
203 
205 {
207 
208  // make sure all worker threads are set up.
209  BeamOn(0);
210  SetRunIDCounter(0);
212 }
213 
215 {
216  //Nothing to do
217 }
219 {
220  //Nothing to do
221 }
223 {
224  //Nothing to do
225 }
226 
228  G4AutoLock l(&cmdHandlingMutex);
229  uiCmdsForWorkers.clear();
230  std::vector<G4String>* cmdCopy = G4UImanager::GetUIpointer()->GetCommandStack();
231  for ( std::vector<G4String>::const_iterator it = cmdCopy->begin() ;
232  it != cmdCopy->end(); ++it )
233  uiCmdsForWorkers.push_back(*it);
234  cmdCopy->clear();
235  delete cmdCopy;
236 }
237 
238 std::vector<G4String> G4MTRunManager::GetCommandStack()
239 {
240  G4AutoLock l(&cmdHandlingMutex);
241  return uiCmdsForWorkers;
242 }
243 
245 {
246  //Now loop on requested number of workers
247  //This will also start the workers
248  //Currently we do not allow to change the
249  //number of threads: threads area created once
250  if ( threads.size() == 0 ) {
251  for ( G4int nw = 0 ; nw<nworkers; ++nw) {
252  //Create a new worker and remember it
253  G4WorkerThread* context = new G4WorkerThread;
254  context->SetNumberThreads(nworkers);
255  context->SetThreadId(nw);
257  threads.push_back(thread);
258  }
259  }
260  //Signal to threads they can start a new run
262 }
263 
264 
265 void G4MTRunManager::InitializeEventLoop(G4int n_event, const char* macroFile, G4int n_select)
266 {
268  numberOfEventToBeProcessed = n_event;
270 
271  if(!fakeRun)
272  {
273  nSeedsUsed = 0;
274  nSeedsFilled = 0;
275 
276  if(verboseLevel>0)
277  { timer->Start(); }
278 
279  n_select_msg = n_select;
280  if(macroFile!=0)
281  {
282  if(n_select_msg<0) n_select_msg = n_event;
283  msgText = "/control/execute ";
284  msgText += macroFile;
285  selectMacro = macroFile;
286  }
287  else
288  {
289  n_select_msg = -1;
290  selectMacro = "";
291  }
292 
293  //initialize seeds
294  //If user did not implement InitializeSeeds,
295  // use default: nSeedsPerEvent seeds per event
296  if( eventModuloDef > 0 )
297  {
300  {
302  if(eventModulo<1) eventModulo =1;
304  msgd << "Event modulo is reduced to " << eventModulo
305  << " to distribute events to all threads.";
306  G4Exception("G4MTRunManager::InitializeEventLoop()",
307  "Run10035", JustWarning, msgd);
308  }
309  }
310  else
311  {
312  eventModulo = int(std::sqrt(double(numberOfEventToBeProcessed/nworkers)));
313  if(eventModulo<1) eventModulo =1;
314  }
315  if ( InitializeSeeds(n_event) == false && n_event>0 )
316  {
318  nSeedsFilled = n_event;
319  // Generates up to nSeedsMax seed pairs only.
322  helper->Fill(randDbl,nSeedsFilled,n_event,nSeedsPerEvent);
323  }
324  }
325 
326  //Now initialize workers. Check if user defined a WorkerThreadInitialization
329 
330  //Prepare UI commands for threads
332 
333  //Start worker threads
335 
336  // We need a barrier here. Wait for workers to start event loop.
337  //This will return only when all workers have started processing events.
339 }
340 
342 {
345  // Generates up to nSeedsMax seed pairs only.
346  if(nFill>nSeedsMax) nFill=nSeedsMax;
347  masterRNGEngine->flatArray(nSeedsPerEvent*nFill,randDbl);
348  helper->Refill(randDbl,nFill);
349  nSeedsFilled += nFill;
350 //G4cout<<"helper->Refill() for "<<nFill<<" events."<<G4endl;
351 }
352 
354 {
355  //Wait for all worker threads to have finished the run
356  //i.e. wait for them to return from RunTermination()
357  //This guarantee that userrunaction for workers has been called
358 
359  // Wait now for all threads to finish event-loop
361  //Now call base-class methof
363 }
364 
365 
367 {
369  //Call base class stuff...
371 
372  masterWorlds.clear();
374  std::vector<G4VPhysicalVolume*>::iterator itrW
376  for(size_t iWorld=0;iWorld<nWorlds;iWorld++)
377  {
378  addWorld(iWorld,*itrW);
379  itrW++;
380  }
381 }
382 
384 {
385  userWorkerInitialization = userInit;
386 }
387 
389 {
391 }
392 
394 {
395  userActionInitialization = userInit;
397 }
398 
400 {
402  //Needed for MT, to be moved in kernel
403 }
404 
406 {
408 }
409 
411 {
412  G4RunManager::SetUserAction(userAction);
413  userAction->SetMaster();
414 }
415 
417 {
418  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
419  "For multi-threaded version, define G4VUserPrimaryGeneratorAction in G4VUserActionInitialization.");
420 }
421 
423 {
424  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
425  "For multi-threaded version, define G4UserEventAction in G4VUserActionInitialization.");
426 }
427 
429 {
430  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
431  "For multi-threaded version, define G4UserStackingAction in G4VUserActionInitialization.");
432 }
433 
435 {
436  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
437  "For multi-threaded version, define G4UserTrackingAction in G4VUserActionInitialization.");
438 }
439 
441 {
442  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
443  "For multi-threaded version, define G4UserSteppingAction in G4VUserActionInitialization.");
444 }
445 
446 void G4MTRunManager::MergeScores(const G4ScoringManager* localScoringManager)
447 {
448  G4AutoLock l(&scorerMergerMutex);
449  if(masterScM) masterScM->Merge(localScoringManager);
450 }
451 
452 void G4MTRunManager::MergeRun(const G4Run* localRun)
453 {
454  G4AutoLock l(&runMergerMutex);
455  if(currentRun) currentRun->Merge(localRun);
456 }
457 
458 G4bool G4MTRunManager::SetUpAnEvent(G4Event* evt,long& s1,long& s2,long& s3)
459 {
460  G4AutoLock l(&setUpEventMutex);
462  {
465  G4int idx_rndm = nSeedsPerEvent*nSeedsUsed;
466  s1 = helper->GetSeed(idx_rndm);
467  s2 = helper->GetSeed(idx_rndm+1);
468  if(nSeedsPerEvent==3) s3 = helper->GetSeed(idx_rndm+2);
470  nSeedsUsed++;
471  if(nSeedsUsed==nSeedsFilled) RefillSeeds();
472  return true;
473  }
474  return false;
475 }
476 
478 {
479  G4AutoLock l(&setUpEventMutex);
481  {
482  G4int nev = eventModulo;
487  for(int i=0;i<nev;i++)
488  {
489  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed));
490  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed+1));
491  if(nSeedsPerEvent==3)
492  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed+2));
493  nSeedsUsed++;
494  if(nSeedsUsed==nSeedsFilled) RefillSeeds();
495  }
496  numberOfEventProcessed += nev;
497  return nev;
498  }
499  return 0;
500 }
501 
503 {
505  //Now join threads.
506 #ifdef G4MULTITHREADED //protect here to prevent warning in compilation
507  while ( ! threads.empty() )
508  {
509  G4Thread* t = * ( threads.begin() );
510  threads.pop_front();
512  //G4THREADJOIN(*t);
513  delete t;
514  }
515 #endif
516  threads.clear();
517 }
518 
519 #include "G4IonTable.hh"
520 #include "G4ParticleTable.hh"
521 #include "G4CascadeInterface.hh"
522 
524 {
526  //BERTINI, this is needed to create pseudo-particles, to be removed
528 }
529 
531 {
532  // This method is valid only for GeomClosed or EventProc state
533  G4ApplicationState currentState =
535  if(currentState==G4State_GeomClosed || currentState==G4State_EventProc)
536  {
537  runAborted = true;
538  MTkernel->BroadcastAbortRun(softAbort);
539  }
540  else
541  {
542  G4cerr << "Run is not in progress. AbortRun() ignored." << G4endl;
543  }
544 }
545 
547 {
548  // nothing to do in the master thread
549 }
550 
551 // =====================================
552 // Barriers mechanism
553 // =====================================
554 // We want to implement barriers.
555 // We define a barrier has a point in which threads synchronize.
556 // When workers threads reach a barrier they wait for the master thread a
557 // signal that they can continue. The master thread broadcast this signal
558 // only when all worker threads have reached this point.
559 // Currently only three points require this sync in the life-time of a G4 applicattion:
560 // Just before and just after the for-loop controlling the thread event-loop.
561 // Between runs.
562 // TODO: If this mechanism is needed in other parts of the code we can provide
563 // the barrier mechanism as a utility class/functions to the kernel.
564 // Note: we need a special treatment for WIN32
565 //
566 // The basic algorith of each barrier works like this:
567 // In the master:
568 // WaitWorkers() {
569 // while (true)
570 // {
571 // G4AutoLock l(&counterMutex); || Mutex is locked (1)
572 // if ( counter == nActiveThreads ) break;
573 // G4CONDITIONWAIT( &conditionOnCounter, &counterMutex); || Mutex is atomically released and wait, upon return locked (2)
574 // } || unlock mutex
575 // G4AutoLock l(&counterMutex); || lock again mutex (3)
576 // G4CONDITIONBROADCAST( &doSomethingCanStart ); || Here mutex is locked (4)
577 // } || final unlock (5)
578 // In the workers:
579 // WaitSignalFromMaster() {
580 // G4AutoLock l(&counterMutex); || (6)
581 // ++counter;
582 // G4CONDITIONBROADCAST(&conditionOnCounter); || (7)
583 // G4CONDITIONWAIT( &doSomethingCanStart , &counterMutex);|| (8)
584 // }
585 // Each barriers requires 2 conditions and one mutex, plus a counter.
586 // Important note: the thread calling broadcast should hold the mutex
587 // before calling broadcast to obtain predictible behavior
588 // http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_cond_broadcast.html
589 // Also remember that the wait for condition will atomically release the mutex
590 // and wait on condition, but it will lock again on mutex when returning
591 // Here it is how the control flows.
592 // Imagine master starts and only one worker (nActiveThreads==1)
593 // Master | Worker | counter | Who holds mutex
594 // Gets to (1) | Blocks on (6) | 0 | M
595 // Waits in (2) | | 0 | -
596 // | Arrives to (7) | 1 | W
597 // | Waits in (8) | 1 | -
598 // Gets to (1) | | 1 | M
599 // Jumps to (3) | | 1 | M
600 // End | | 1 | -
601 // | End | 1 | -
602 // Similarly for more than one worker threads or if worker starts
603 
604 #ifdef WIN32
605 #include <windows.h> //For CRITICAL_SECTION objects
606 #endif
607 namespace {
608  //Avoid compilation warning if squenetial for unused variables
609 #ifdef G4MULTITHREADED
610  //Conditions
611  // Condition to signal green light for start of event loop
612  G4Condition beginEventLoopCondition = G4CONDITION_INITIALIZER;
613  // Condition to signal green light to finish event loop
614  // (actuallyt exit function performing event loop)
615  G4Condition endEventLoopCondition = G4CONDITION_INITIALIZER;
616  // Condition to signal the num of workers ready for event loop has changed
617  G4Condition numWorkersBeginEventLoopChangeCondition = G4CONDITION_INITIALIZER;
618  // Condition to signal the num of workers that terminated event loop
619  // has changed
620  G4Condition numWorkersEndEventLoopChangedCondition = G4CONDITION_INITIALIZER;
621  // This condition is to handle more than one run w/o killing threads
622  G4Condition requestChangeActionForWorker = G4CONDITION_INITIALIZER;
623  G4Condition numberOfReadyWorkersForNewActionChangedCondition = G4CONDITION_INITIALIZER;
624 #endif
625  // Counter/mutex for workers ready to begin event loop
626  G4Mutex numberOfReadyWorkersMutex = G4MUTEX_INITIALIZER;
627  G4int numberOfReadyWorkers = 0;
628  //Counter/mutex for workers with end of event loop
629  G4Mutex numberOfEndOfEventLoopWorkersMutex = G4MUTEX_INITIALIZER;
630  G4int numberOfEndOfEventLoopWorkers = 0;
631  //
632  //Action handling
633  G4Mutex nextActionRequestMutex = G4MUTEX_INITIALIZER;
634  G4int numberOfReadyWorkersForNewAction = 0;
635  G4Mutex numberOfReadyWorkersForNewActionMutex = G4MUTEX_INITIALIZER;
636 #ifdef WIN32
637  CRITICAL_SECTION cs1;
638  CRITICAL_SECTION cs2;
639  CRITICAL_SECTION cs3;
640  //Note we need to use two separate counters because
641  //we can get a situation in which a thread is much faster then the others
642  //(for example if last thread has less events to process.
643  //We have the extreme case of some medical applications (moving setups)
644  //in which the number of events of a run is ~ number of threads
645  void InitializeWindowsConditions()
646  {
647  #ifdef G4MULTITHREADED
648  InitializeConditionVariable( &beginEventLoopCondition );
649  InitializeConditionVariable( &endEventLoopCondition );
650  InitializeConditionVariable( &numWorkersBeginEventLoopChangeCondition );
651  InitializeConditionVariable( &numWorkersEndEventLoopChangedCondition );
652  InitializeConditionVariable( &requestChangeActionForWorker);
653  InitializeConditionVariable( &numberOfReadyWorkersForNewActionChangedCondition );
654  #endif
655  InitializeCriticalSection( &cs1 );
656  InitializeCriticalSection( &cs2 );
657  InitializeCriticalSection( &cs3 );
658  }
659 #endif
660 }
661 
663 {
664  while (true) //begin barrier
665  {
666 #ifndef WIN32
667  G4AutoLock lockLoop(&numberOfReadyWorkersMutex);
668 #else
669  EnterCriticalSection( &cs1 );
670 #endif
671  //Check number of workers ready to begin
672  G4int activethreads = threads.size();
673  if (numberOfReadyWorkers == activethreads )
674  {
675  //Ok, interrupt the loop
676  break;
677  }
678  //Wait for the number of workers to be changed
679 #ifdef WIN32
680  G4CONDITIONWAIT(&numWorkersBeginEventLoopChangeCondition,
681  &cs1);
682  LeaveCriticalSection( &cs1 );
683 #else
684  G4CONDITIONWAIT(&numWorkersBeginEventLoopChangeCondition,
685  &numberOfReadyWorkersMutex);
686 #endif
687  }
688  //Now number of workers is as expected.
707 
708  //Prepare to wait for workers to end eventloop
709  //Reset number of workers in "EndOfEventLoop"
710  G4AutoLock l(&numberOfEndOfEventLoopWorkersMutex);
711  numberOfEndOfEventLoopWorkers = 0;
712 
713  //signal workers they can start the event-loop
714  G4AutoLock l2(&numberOfReadyWorkersMutex);
715  G4CONDTIONBROADCAST(&beginEventLoopCondition);
716 }
717 
719 {
720  //Increament number of active worker by 1
721 #ifndef WIN32
722  G4AutoLock lockLoop(&numberOfReadyWorkersMutex);
723 #else
724  EnterCriticalSection( &cs1 );
725 #endif
726  ++numberOfReadyWorkers;
727  //Signal the number of workers has changed
728  G4CONDTIONBROADCAST(&numWorkersBeginEventLoopChangeCondition);
729  //Wait for condition to start eventloop
730 #ifdef WIN32
731  G4CONDITIONWAIT(&beginEventLoopCondition,&cs1);
732  LeaveCriticalSection( &cs1 );
733 #else
734  G4CONDITIONWAIT(&beginEventLoopCondition,&numberOfReadyWorkersMutex);
735 #endif
736  //Protects access to shared resource, guarantees we do not call this method
737  //while someone else is modifying its content (e.g. creating a new particle)
738  //G4PDefManager& pdm = const_cast<G4PDefManager&>(G4ParticleDefinition::GetSubInstanceManager());
739  //pdm.Lock();
740  //pdm.NewSubInstances();
741  //pdm.UnLock();
742  //const_cast<G4PDefManager&>(G4ParticleDefinition::GetSubInstanceManager()).NewSubInstances();
743  // I believe this is not necessary and safe to remove (Makoto)
744  //G4ParticleTable::GetParticleTable()->WorkerG4ParticleTable();
745 }
746 
747 
749 {
750  while (true)
751  {
752 #ifndef WIN32
753  G4AutoLock l(&numberOfEndOfEventLoopWorkersMutex);
754 #else
755  EnterCriticalSection( &cs2 );
756 #endif
757  G4int activethreads = threads.size();
758  if ( numberOfEndOfEventLoopWorkers == activethreads )
759  {
760  break;
761  }
762 #ifdef WIN32
763  G4CONDITIONWAIT(&numWorkersEndEventLoopChangedCondition,
764  &cs2);
765  LeaveCriticalSection( &cs2 );
766 #else
767  G4CONDITIONWAIT(&numWorkersEndEventLoopChangedCondition,
768  &numberOfEndOfEventLoopWorkersMutex);
769 #endif
770  }
771  //Now number of workers that reached end of event loop is as expected
772  //Reset number of workers in ready for work state so a new run can start
773  G4AutoLock l(&numberOfReadyWorkersMutex);
774  numberOfReadyWorkers = 0;
775  //Signal workers they can end event-loop
776  G4AutoLock l2(&numberOfEndOfEventLoopWorkersMutex);
777  G4CONDTIONBROADCAST(&endEventLoopCondition);
778 }
779 
781 {
782  //Increament number of workers in end of evnet loop by 1
783 #ifndef WIN32
784  G4AutoLock l(&numberOfEndOfEventLoopWorkersMutex);
785 #else
786  EnterCriticalSection( &cs2 );
787 #endif
788  ++numberOfEndOfEventLoopWorkers;
789  //Signale this number has changed
790  G4CONDTIONBROADCAST(&numWorkersEndEventLoopChangedCondition);
791  //Wait for condition to exit eventloop
792 #ifdef WIN32
793  G4CONDITIONWAIT(&endEventLoopCondition,&cs2);
794  LeaveCriticalSection( &cs2 );
795 #else
796  G4CONDITIONWAIT(&endEventLoopCondition,&numberOfEndOfEventLoopWorkersMutex);
797 #endif
798 }
799 
801 {
802  //Wait for all workers to be ready to accept a new action request
803  while (true)
804  {
805 #ifndef WIN32
806  G4AutoLock l(&numberOfReadyWorkersForNewActionMutex);
807 #else
808  EnterCriticalSection( &cs3 );
809 #endif
810  //Check the number of workers that are ready for next action
811  G4int activethreads = threads.size();
812  if ( numberOfReadyWorkersForNewAction == activethreads )
813  {
814  //Ok, exit the loop
815  break;
816  }
817  //Wait for the number of workers ready for new action to change
818 #ifdef WIN32
819  G4CONDITIONWAIT(&numberOfReadyWorkersForNewActionChangedCondition,
820  &cs3);
821  LeaveCriticalSection( &cs3 );
822 #else
823  G4CONDITIONWAIT(&numberOfReadyWorkersForNewActionChangedCondition,
824  &numberOfReadyWorkersForNewActionMutex);
825 #endif
826  }
827  //Now set the new action to the shared resource
828  G4AutoLock l(&nextActionRequestMutex);
829  nextActionRequest = newRequest;
830  l.unlock();
831  //Reset counter of workers ready-for-new-action in preparation of next call
832  G4AutoLock l2(&numberOfReadyWorkersForNewActionMutex);
833  numberOfReadyWorkersForNewAction = 0;
834  //l2.unlock(); //<----- This thread needs to have control on mutex associated
835  //to condition variable (report from valgrind --tool=drd)
836  //see: http://pic.dhe.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Fapis%2Fusers_73.htm
837  //Now signal all workers that there is a new action to be performed
838  G4CONDTIONBROADCAST(&requestChangeActionForWorker);
839 }
840 
842 {
843  //This worker is ready to receive a new action request,
844  //increment counter by 1
845  #ifndef WIN32
846  G4AutoLock l(&numberOfReadyWorkersForNewActionMutex);
847 #else
848  EnterCriticalSection( &cs3 );
849 #endif
850  ++numberOfReadyWorkersForNewAction;
851  //Singal the sahred resource has changed to the master
852  G4CONDTIONBROADCAST(&numberOfReadyWorkersForNewActionChangedCondition);
853  //Wait for condition that a new aciton is ready
854 #ifdef WIN32
855  G4CONDITIONWAIT(&requestChangeActionForWorker,&cs3);
856  LeaveCriticalSection( &cs3 );
857 #else
858  G4CONDITIONWAIT(&requestChangeActionForWorker,&numberOfReadyWorkersForNewActionMutex);
859 #endif
860  //Ok, if I am here it means that a new action has been requested by the master
861  //reads it value that is now read-only, so no mutex is needed, but you never know...
862  G4AutoLock l2(&nextActionRequestMutex);
864  return result;
865 }
G4Timer * timer
virtual void InitializeEventLoop(G4int n_event, const char *macroFile=0, G4int n_select=-1)
void SetMaster(G4bool val=true)
static G4TemplateRNGHelper * GetInstance()
Definition: G4RNGHelper.hh:52
std::vector< G4String > GetCommandStack()
virtual void PrepareCommandsStack()
virtual void SetUserInitialization(G4VUserDetectorConstruction *userInit)
virtual void Merge(const G4Run *)
Definition: G4Run.cc:54
std::map< G4int, G4VPhysicalVolume * > masterWorlds_t
G4int n_select_msg
std::vector< G4String > uiCmdsForWorkers
void Fill(double *dbl, int nev, int nev_tot, int nrpe)
Definition: G4RNGHelper.hh:95
virtual G4bool SetUpAnEvent(G4Event *, long &s1, long &s2, long &s3)
G4int numberOfEventProcessed
static void addWorld(G4int counter, G4VPhysicalVolume *w)
WorkerActionRequest nextActionRequest
virtual void RunTermination()
std::ostringstream G4ExceptionDescription
Definition: globals.hh:76
virtual void ThisWorkerEndEventLoop()
void SetNumberOfThreads(G4int n)
std::vector< G4VPhysicalVolume * >::iterator GetWorldsIterator()
G4VUserActionInitialization * userActionInitialization
#define G4CONDTIONBROADCAST(cond)
Definition: G4Threading.hh:173
G4UserWorkerThreadInitialization * userWorkerThreadInitialization
virtual G4bool InitializeSeeds(G4int)
virtual void ConstructScoringWorlds()
virtual void BeamOn(G4int n_event, const char *macroFile=0, G4int n_select=-1)
virtual void RunTermination()
virtual const T GetSeed(const G4int &sdId)
Definition: G4RNGHelper.hh:77
virtual void InitializePhysics()
void SetThreadId(G4int threadId)
G4String msgText
int G4int
Definition: G4Types.hh:78
#define G4CONDITIONWAIT(cond, mutex)
Definition: G4Threading.hh:172
G4bool runAborted
std::vector< G4String > * GetCommandStack()
Definition: G4UImanager.cc:682
virtual void SetUserAction(G4UserRunAction *userAction)
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:158
std::queue< long > G4SeedsQueue
Definition: G4RNGHelper.hh:133
G4int G4Thread
Definition: G4Threading.hh:157
virtual void WaitForEndEventLoopWorkers()
G4MTRunManagerKernel * MTkernel
virtual void TerminateOneEvent()
static G4UImanager * GetUIpointer()
Definition: G4UImanager.cc:58
virtual void TerminateWorkers()
static G4StateManager * GetStateManager()
static G4RunManagerKernel * GetMasterRunManagerKernel()
G4ThreadsList threads
G4GLOB_DLL std::ostream G4cout
virtual void InitializePhysics()
void MergeRun(const G4Run *localRun)
static masterWorlds_t masterWorlds
static G4ScoringManager * GetScoringManagerIfExist()
void Refill(double *dbl, int nev)
Definition: G4RNGHelper.hh:106
static G4ScoringManager * masterScM
G4UserWorkerInitialization * userWorkerInitialization
G4String randomNumberStatusDir
virtual void ProcessOneEvent(G4int i_event)
bool G4bool
Definition: G4Types.hh:79
virtual void ConstructScoringWorlds()
virtual void WaitForReadyWorkers()
virtual G4int SetUpNEvents(G4Event *, G4SeedsQueue *seedsQueue)
static G4MTRunManager * GetMasterRunManager()
G4int G4GetNumberOfCores()
Definition: G4Threading.cc:102
virtual WorkerActionRequest ThisWorkerWaitForNextAction()
Definition: G4Run.hh:46
virtual void SetUserInitialization(G4VUserPhysicsList *userPL)
virtual void AbortRun(G4bool softAbort=false)
G4ApplicationState GetCurrentState() const
virtual void NewActionRequest(WorkerActionRequest newRequest)
const G4int n
void Merge(const G4ScoringManager *scMan)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
static G4TransportationManager * GetTransportationManager()
G4int G4Mutex
Definition: G4Threading.hh:156
virtual void Initialize()
G4String selectMacro
virtual void ThisWorkerReady()
virtual void AbortEvent()
void SetRunIDCounter(G4int i)
virtual G4Thread * CreateAndStartWorker(G4WorkerThread *workerThreadContext)
virtual ~G4MTRunManager()
virtual void Initialize()
size_t GetNoWorlds() const
G4int numberOfEventToBeProcessed
G4Run * currentRun
#define G4endl
Definition: G4ios.hh:61
G4int GetNumberOfStaticAllocators() const
G4RunManagerKernel * kernel
void Start()
void BroadcastAbortRun(G4bool softAbort)
static G4MTRunManagerKernel * GetMTMasterRunManagerKernel()
void SetNumberThreads(G4int numnberThreads)
void MergeScores(const G4ScoringManager *localScoringManager)
void SetEventID(G4int i)
Definition: G4Event.hh:114
CLHEP::HepRandomEngine * masterRNGEngine
virtual void TerminateEventLoop()
G4int G4Condition
Definition: G4Threading.hh:170
void SetMasterUIManager(G4bool val)
Definition: G4UImanager.hh:258
G4ApplicationState
virtual void StoreRNGStatus(const G4String &filenamePrefix)
G4int verboseLevel
G4GLOB_DLL std::ostream G4cerr
virtual void SetUserAction(G4UserRunAction *userAction)
virtual void CreateAndStartWorkers()
#define G4CONDITION_INITIALIZER
Definition: G4Threading.hh:171
static G4MTRunManager * fMasterRM