Geant4  10.00.p03
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 
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 method
364 }
365 
366 
368 {
370  //Call base class stuff...
372 
373  masterWorlds.clear();
375  std::vector<G4VPhysicalVolume*>::iterator itrW
377  for(size_t iWorld=0;iWorld<nWorlds;iWorld++)
378  {
379  addWorld(iWorld,*itrW);
380  itrW++;
381  }
382 }
383 
385 {
386  userWorkerInitialization = userInit;
387 }
388 
390 {
392 }
393 
395 {
396  userActionInitialization = userInit;
398 }
399 
401 {
403  //Needed for MT, to be moved in kernel
404 }
405 
407 {
409 }
410 
412 {
413  G4RunManager::SetUserAction(userAction);
414  userAction->SetMaster();
415 }
416 
418 {
419  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
420  "For multi-threaded version, define G4VUserPrimaryGeneratorAction in G4VUserActionInitialization.");
421 }
422 
424 {
425  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
426  "For multi-threaded version, define G4UserEventAction in G4VUserActionInitialization.");
427 }
428 
430 {
431  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
432  "For multi-threaded version, define G4UserStackingAction in G4VUserActionInitialization.");
433 }
434 
436 {
437  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
438  "For multi-threaded version, define G4UserTrackingAction in G4VUserActionInitialization.");
439 }
440 
442 {
443  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
444  "For multi-threaded version, define G4UserSteppingAction in G4VUserActionInitialization.");
445 }
446 
447 void G4MTRunManager::MergeScores(const G4ScoringManager* localScoringManager)
448 {
449  G4AutoLock l(&scorerMergerMutex);
450  if(masterScM) masterScM->Merge(localScoringManager);
451 }
452 
453 void G4MTRunManager::MergeRun(const G4Run* localRun)
454 {
455  G4AutoLock l(&runMergerMutex);
456  if(currentRun) currentRun->Merge(localRun);
457 }
458 
459 G4bool G4MTRunManager::SetUpAnEvent(G4Event* evt,long& s1,long& s2,long& s3)
460 {
461  G4AutoLock l(&setUpEventMutex);
463  {
466  G4int idx_rndm = nSeedsPerEvent*nSeedsUsed;
467  s1 = helper->GetSeed(idx_rndm);
468  s2 = helper->GetSeed(idx_rndm+1);
469  if(nSeedsPerEvent==3) s3 = helper->GetSeed(idx_rndm+2);
471  nSeedsUsed++;
472  if(nSeedsUsed==nSeedsFilled) RefillSeeds();
473  return true;
474  }
475  return false;
476 }
477 
479 {
480  G4AutoLock l(&setUpEventMutex);
482  {
483  G4int nev = eventModulo;
488  for(int i=0;i<nev;i++)
489  {
490  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed));
491  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed+1));
492  if(nSeedsPerEvent==3)
493  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed+2));
494  nSeedsUsed++;
495  if(nSeedsUsed==nSeedsFilled) RefillSeeds();
496  }
497  numberOfEventProcessed += nev;
498  return nev;
499  }
500  return 0;
501 }
502 
504 {
506  //Now join threads.
507 #ifdef G4MULTITHREADED //protect here to prevent warning in compilation
508  while ( ! threads.empty() )
509  {
510  G4Thread* t = * ( threads.begin() );
511  threads.pop_front();
513  //G4THREADJOIN(*t);
514  delete t;
515  }
516 #endif
517  threads.clear();
518 }
519 
520 #include "G4IonTable.hh"
521 #include "G4ParticleTable.hh"
522 #include "G4CascadeInterface.hh"
523 
525 {
527  //BERTINI, this is needed to create pseudo-particles, to be removed
529 }
530 
532 {
533  // This method is valid only for GeomClosed or EventProc state
534  G4ApplicationState currentState =
536  if(currentState==G4State_GeomClosed || currentState==G4State_EventProc)
537  {
538  runAborted = true;
539  MTkernel->BroadcastAbortRun(softAbort);
540  }
541  else
542  {
543  G4cerr << "Run is not in progress. AbortRun() ignored." << G4endl;
544  }
545 }
546 
548 {
549  // nothing to do in the master thread
550 }
551 
552 // =====================================
553 // Barriers mechanism
554 // =====================================
555 // We want to implement barriers.
556 // We define a barrier has a point in which threads synchronize.
557 // When workers threads reach a barrier they wait for the master thread a
558 // signal that they can continue. The master thread broadcast this signal
559 // only when all worker threads have reached this point.
560 // Currently only three points require this sync in the life-time of a G4 applicattion:
561 // Just before and just after the for-loop controlling the thread event-loop.
562 // Between runs.
563 // TODO: If this mechanism is needed in other parts of the code we can provide
564 // the barrier mechanism as a utility class/functions to the kernel.
565 // Note: we need a special treatment for WIN32
566 //
567 // The basic algorith of each barrier works like this:
568 // In the master:
569 // WaitWorkers() {
570 // while (true)
571 // {
572 // G4AutoLock l(&counterMutex); || Mutex is locked (1)
573 // if ( counter == nActiveThreads ) break;
574 // G4CONDITIONWAIT( &conditionOnCounter, &counterMutex); || Mutex is atomically released and wait, upon return locked (2)
575 // } || unlock mutex
576 // G4AutoLock l(&counterMutex); || lock again mutex (3)
577 // G4CONDITIONBROADCAST( &doSomethingCanStart ); || Here mutex is locked (4)
578 // } || final unlock (5)
579 // In the workers:
580 // WaitSignalFromMaster() {
581 // G4AutoLock l(&counterMutex); || (6)
582 // ++counter;
583 // G4CONDITIONBROADCAST(&conditionOnCounter); || (7)
584 // G4CONDITIONWAIT( &doSomethingCanStart , &counterMutex);|| (8)
585 // }
586 // Each barriers requires 2 conditions and one mutex, plus a counter.
587 // Important note: the thread calling broadcast should hold the mutex
588 // before calling broadcast to obtain predictible behavior
589 // http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_cond_broadcast.html
590 // Also remember that the wait for condition will atomically release the mutex
591 // and wait on condition, but it will lock again on mutex when returning
592 // Here it is how the control flows.
593 // Imagine master starts and only one worker (nActiveThreads==1)
594 // Master | Worker | counter | Who holds mutex
595 // Gets to (1) | Blocks on (6) | 0 | M
596 // Waits in (2) | | 0 | -
597 // | Arrives to (7) | 1 | W
598 // | Waits in (8) | 1 | -
599 // Gets to (1) | | 1 | M
600 // Jumps to (3) | | 1 | M
601 // End | | 1 | -
602 // | End | 1 | -
603 // Similarly for more than one worker threads or if worker starts
604 
605 #ifdef WIN32
606 #include <windows.h> //For CRITICAL_SECTION objects
607 #endif
608 namespace {
609  //Avoid compilation warning if squenetial for unused variables
610 #ifdef G4MULTITHREADED
611  //Conditions
612  // Condition to signal green light for start of event loop
613  G4Condition beginEventLoopCondition = G4CONDITION_INITIALIZER;
614  // Condition to signal green light to finish event loop
615  // (actuallyt exit function performing event loop)
616  G4Condition endEventLoopCondition = G4CONDITION_INITIALIZER;
617  // Condition to signal the num of workers ready for event loop has changed
618  G4Condition numWorkersBeginEventLoopChangeCondition = G4CONDITION_INITIALIZER;
619  // Condition to signal the num of workers that terminated event loop
620  // has changed
621  G4Condition numWorkersEndEventLoopChangedCondition = G4CONDITION_INITIALIZER;
622  // This condition is to handle more than one run w/o killing threads
623  G4Condition requestChangeActionForWorker = G4CONDITION_INITIALIZER;
624  G4Condition numberOfReadyWorkersForNewActionChangedCondition = G4CONDITION_INITIALIZER;
625 #endif
626  // Counter/mutex for workers ready to begin event loop
627  G4Mutex numberOfReadyWorkersMutex = G4MUTEX_INITIALIZER;
628  G4int numberOfReadyWorkers = 0;
629  //Counter/mutex for workers with end of event loop
630  G4Mutex numberOfEndOfEventLoopWorkersMutex = G4MUTEX_INITIALIZER;
631  G4int numberOfEndOfEventLoopWorkers = 0;
632  //
633  //Action handling
634  G4Mutex nextActionRequestMutex = G4MUTEX_INITIALIZER;
635  G4int numberOfReadyWorkersForNewAction = 0;
636  G4Mutex numberOfReadyWorkersForNewActionMutex = G4MUTEX_INITIALIZER;
637 #ifdef WIN32
638  CRITICAL_SECTION cs1;
639  CRITICAL_SECTION cs2;
640  CRITICAL_SECTION cs3;
641  //Note we need to use two separate counters because
642  //we can get a situation in which a thread is much faster then the others
643  //(for example if last thread has less events to process.
644  //We have the extreme case of some medical applications (moving setups)
645  //in which the number of events of a run is ~ number of threads
646  void InitializeWindowsConditions()
647  {
648  #ifdef G4MULTITHREADED
649  InitializeConditionVariable( &beginEventLoopCondition );
650  InitializeConditionVariable( &endEventLoopCondition );
651  InitializeConditionVariable( &numWorkersBeginEventLoopChangeCondition );
652  InitializeConditionVariable( &numWorkersEndEventLoopChangedCondition );
653  InitializeConditionVariable( &requestChangeActionForWorker);
654  InitializeConditionVariable( &numberOfReadyWorkersForNewActionChangedCondition );
655  #endif
656  InitializeCriticalSection( &cs1 );
657  InitializeCriticalSection( &cs2 );
658  InitializeCriticalSection( &cs3 );
659  }
660 #endif
661 }
662 
664 {
665  while (true) //begin barrier
666  {
667 #ifndef WIN32
668  G4AutoLock lockLoop(&numberOfReadyWorkersMutex);
669 #else
670  EnterCriticalSection( &cs1 );
671 #endif
672  //Check number of workers ready to begin
673  G4int activethreads = threads.size();
674  if (numberOfReadyWorkers == activethreads )
675  {
676  //Ok, interrupt the loop
677  break;
678  }
679  //Wait for the number of workers to be changed
680 #ifdef WIN32
681  G4CONDITIONWAIT(&numWorkersBeginEventLoopChangeCondition,
682  &cs1);
683  LeaveCriticalSection( &cs1 );
684 #else
685  G4CONDITIONWAIT(&numWorkersBeginEventLoopChangeCondition,
686  &numberOfReadyWorkersMutex);
687 #endif
688  }
689  //Now number of workers is as expected.
708 
709  //Prepare to wait for workers to end eventloop
710  //Reset number of workers in "EndOfEventLoop"
711  G4AutoLock l(&numberOfEndOfEventLoopWorkersMutex);
712  numberOfEndOfEventLoopWorkers = 0;
713 
714  //signal workers they can start the event-loop
715  G4AutoLock l2(&numberOfReadyWorkersMutex);
716  G4CONDTIONBROADCAST(&beginEventLoopCondition);
717 }
718 
720 {
721  //Increament number of active worker by 1
722 #ifndef WIN32
723  G4AutoLock lockLoop(&numberOfReadyWorkersMutex);
724 #else
725  EnterCriticalSection( &cs1 );
726 #endif
727  ++numberOfReadyWorkers;
728  //Signal the number of workers has changed
729  G4CONDTIONBROADCAST(&numWorkersBeginEventLoopChangeCondition);
730  //Wait for condition to start eventloop
731 #ifdef WIN32
732  G4CONDITIONWAIT(&beginEventLoopCondition,&cs1);
733  LeaveCriticalSection( &cs1 );
734 #else
735  G4CONDITIONWAIT(&beginEventLoopCondition,&numberOfReadyWorkersMutex);
736 #endif
737  //Protects access to shared resource, guarantees we do not call this method
738  //while someone else is modifying its content (e.g. creating a new particle)
739  //G4PDefManager& pdm = const_cast<G4PDefManager&>(G4ParticleDefinition::GetSubInstanceManager());
740  //pdm.Lock();
741  //pdm.NewSubInstances();
742  //pdm.UnLock();
743  //const_cast<G4PDefManager&>(G4ParticleDefinition::GetSubInstanceManager()).NewSubInstances();
744  // I believe this is not necessary and safe to remove (Makoto)
745  //G4ParticleTable::GetParticleTable()->WorkerG4ParticleTable();
746 }
747 
748 
750 {
751  while (true)
752  {
753 #ifndef WIN32
754  G4AutoLock l(&numberOfEndOfEventLoopWorkersMutex);
755 #else
756  EnterCriticalSection( &cs2 );
757 #endif
758  G4int activethreads = threads.size();
759  if ( numberOfEndOfEventLoopWorkers == activethreads )
760  {
761  break;
762  }
763 #ifdef WIN32
764  G4CONDITIONWAIT(&numWorkersEndEventLoopChangedCondition,
765  &cs2);
766  LeaveCriticalSection( &cs2 );
767 #else
768  G4CONDITIONWAIT(&numWorkersEndEventLoopChangedCondition,
769  &numberOfEndOfEventLoopWorkersMutex);
770 #endif
771  }
772  //Now number of workers that reached end of event loop is as expected
773  //Reset number of workers in ready for work state so a new run can start
774  G4AutoLock l(&numberOfReadyWorkersMutex);
775  numberOfReadyWorkers = 0;
776  //Signal workers they can end event-loop
777  G4AutoLock l2(&numberOfEndOfEventLoopWorkersMutex);
778  G4CONDTIONBROADCAST(&endEventLoopCondition);
779 }
780 
782 {
783  //Increament number of workers in end of evnet loop by 1
784 #ifndef WIN32
785  G4AutoLock l(&numberOfEndOfEventLoopWorkersMutex);
786 #else
787  EnterCriticalSection( &cs2 );
788 #endif
789  ++numberOfEndOfEventLoopWorkers;
790  //Signale this number has changed
791  G4CONDTIONBROADCAST(&numWorkersEndEventLoopChangedCondition);
792  //Wait for condition to exit eventloop
793 #ifdef WIN32
794  G4CONDITIONWAIT(&endEventLoopCondition,&cs2);
795  LeaveCriticalSection( &cs2 );
796 #else
797  G4CONDITIONWAIT(&endEventLoopCondition,&numberOfEndOfEventLoopWorkersMutex);
798 #endif
799 }
800 
802 {
803  //Wait for all workers to be ready to accept a new action request
804  while (true)
805  {
806 #ifndef WIN32
807  G4AutoLock l(&numberOfReadyWorkersForNewActionMutex);
808 #else
809  EnterCriticalSection( &cs3 );
810 #endif
811  //Check the number of workers that are ready for next action
812  G4int activethreads = threads.size();
813  if ( numberOfReadyWorkersForNewAction == activethreads )
814  {
815  //Ok, exit the loop
816  break;
817  }
818  //Wait for the number of workers ready for new action to change
819 #ifdef WIN32
820  G4CONDITIONWAIT(&numberOfReadyWorkersForNewActionChangedCondition,
821  &cs3);
822  LeaveCriticalSection( &cs3 );
823 #else
824  G4CONDITIONWAIT(&numberOfReadyWorkersForNewActionChangedCondition,
825  &numberOfReadyWorkersForNewActionMutex);
826 #endif
827  }
828  //Now set the new action to the shared resource
829  G4AutoLock l(&nextActionRequestMutex);
830  nextActionRequest = newRequest;
831  l.unlock();
832  //Reset counter of workers ready-for-new-action in preparation of next call
833  G4AutoLock l2(&numberOfReadyWorkersForNewActionMutex);
834  numberOfReadyWorkersForNewAction = 0;
835  //l2.unlock(); //<----- This thread needs to have control on mutex associated
836  //to condition variable (report from valgrind --tool=drd)
837  //see: http://pic.dhe.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Fapis%2Fusers_73.htm
838  //Now signal all workers that there is a new action to be performed
839  G4CONDTIONBROADCAST(&requestChangeActionForWorker);
840 }
841 
843 {
844  //This worker is ready to receive a new action request,
845  //increment counter by 1
846  #ifndef WIN32
847  G4AutoLock l(&numberOfReadyWorkersForNewActionMutex);
848 #else
849  EnterCriticalSection( &cs3 );
850 #endif
851  ++numberOfReadyWorkersForNewAction;
852  //Singal the sahred resource has changed to the master
853  G4CONDTIONBROADCAST(&numberOfReadyWorkersForNewActionChangedCondition);
854  //Wait for condition that a new aciton is ready
855 #ifdef WIN32
856  G4CONDITIONWAIT(&requestChangeActionForWorker,&cs3);
857  LeaveCriticalSection( &cs3 );
858 #else
859  G4CONDITIONWAIT(&requestChangeActionForWorker,&numberOfReadyWorkersForNewActionMutex);
860 #endif
861  //Ok, if I am here it means that a new action has been requested by the master
862  //reads it value that is now read-only, so no mutex is needed, but you never know...
863  G4AutoLock l2(&nextActionRequestMutex);
865  return result;
866 }
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
virtual void TerminateEventLoop()
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:695
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
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