Geant4  10.01.p02
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 
50 
51 namespace {
52  G4Mutex cmdHandlingMutex = G4MUTEX_INITIALIZER;
53  G4Mutex scorerMergerMutex = G4MUTEX_INITIALIZER;
54  G4Mutex runMergerMutex = G4MUTEX_INITIALIZER;
55  G4Mutex setUpEventMutex = G4MUTEX_INITIALIZER;
56 }
57 
58 //This is needed to initialize windows conditions
59 #if defined(WIN32)
60 namespace {
61  void InitializeWindowsConditions();
62 }
63 #endif
64 
66 {
68  return fMasterRM;
72 }
73 
75 {
76  return fMasterRM->kernel;
77 }
78 
80 {
81  return fMasterRM->MTkernel;
82 }
83 
85  nworkers(2),forcedNwokers(-1),pinAffinity(0),
86  masterRNGEngine(0),
87  nextActionRequest(UNDEFINED),
88  eventModuloDef(0),eventModulo(1),
89  nSeedsUsed(0),nSeedsFilled(0),
90  nSeedsMax(10000),nSeedsPerEvent(2)
91 {
92  if ( fMasterRM )
93  {
94  G4Exception("G4MTRunManager::G4MTRunManager", "Run0035",FatalException,
95  "Another instance of a G4MTRunManager already exists.");
96  }
97  fMasterRM = this;
98  MTkernel = static_cast<G4MTRunManagerKernel*>(kernel);
99 #ifndef G4MULTITHREADED
101  msg << "Geant4 code is compiled without multi-threading support"
102  << "(-DG4MULTITHREADED is set to off).\n";
103  msg << "G4MTRunManager can only be used in multi-threaded applications.";
104  G4Exception("G4MTRunManager::G4MTRunManager","Run0035",FatalException,msg);
105 #endif
106 
107  G4int numberOfStaticAllocators = kernel->GetNumberOfStaticAllocators();
108  if(numberOfStaticAllocators>0)
109  {
111  msg1 << "There are " << numberOfStaticAllocators
112  << " static G4Allocator objects detected.\n"
113  << "In multi-threaded mode, all G4Allocator objects must be dynamicly instantiated.";
114  G4Exception("G4MTRunManager::G4MTRunManager","Run1035",FatalException,msg1);
115  }
118 
119  //Check if a default RandomNumberGenerator has been created by user,
120  // if not create default one
121  //Note this call forces creation of defaults if not already there
122  //G4Random::getTheEngine(); //User did not specify RNG, create defaults
123  //Now remember the master instance of the RNG Engine
124  masterRNGEngine = G4Random::getTheEngine();
125 #if defined (WIN32)
126  InitializeWindowsConditions();
127 #endif
128 
130  randDbl = new double[nSeedsPerEvent*nSeedsMax];
131 
132  char* env = getenv("G4FORCENUMBEROFTHREADS");
133  if(env)
134  {
135  G4String envS = env;
136  if(envS=="MAX"||envS=="max")
138  else
139  {
140  std::istringstream is(env);
141  G4int val = -1;
142  is >> val;
143  if(val>0)
144  { forcedNwokers = val; }
145  else
146  {
148  msg2 << "Environment variable G4FORCENUMBEROFTHREADS has an invalid value <"
149  << envS << ">. It has to be an integer or a word \"max\".\n"
150  << "G4FORCENUMBEROFTHREADS is ignored.";
151  G4Exception("G4MTRunManager::G4MTRunManager","Run1039",JustWarning,msg2);
152  }
153  }
154  if(forcedNwokers>0)
155  {
157  G4cout << "### Number of threads is forced to " << forcedNwokers
158  << " by Environment variable G4FORCENUMBEROFTHREADS." << G4endl;
159  }
160  }
161 }
162 
164 {
165  //TODO: Currently does not work due to concurrent deletion of something
166  // that is shared:
167  //G4ProcessTable::DeleteMessenger from ~G4RunManager
168  //G4cout<<"Destroy MTRunManager"<<G4endl;//ANDREA
170  delete [] randDbl;
171 }
172 
174 {
175  std::ostringstream os;
176  os << randomNumberStatusDir << "G4Master_"<<fn <<".rndm";
177  G4Random::saveEngineStatus(os.str().c_str());
178 }
179 
181 {
182  if ( threads.size() != 0 )
183  {
185  msg << "Number of threads cannot be changed at this moment \n"
186  << "(old threads are still alive). Method ignored.";
187  G4Exception("G4MTRunManager::SetNumberOfThreads(G4int)",
188  "Run0035", JustWarning, msg);
189  }
190  else if ( forcedNwokers > 0 )
191  {
193  msg << "Number of threads is forced to " << forcedNwokers
194  << " by G4FORCENUMBEROFWORKERS shell variable.\n"
195  << "Method ignored.";
196  G4Exception("G4MTRunManager::SetNumberOfThreads(G4int)",
197  "Run0035", JustWarning, msg);
198  }
199  else
200  {
201  nworkers = n;
202  }
203 }
204 
206 {
208 
209  // make sure all worker threads are set up.
210  BeamOn(0);
211  SetRunIDCounter(0);
213 }
214 
220 {
221  //Nothing to do
222 }
224 {
225  //Nothing to do
226 }
227 
229  G4AutoLock l(&cmdHandlingMutex);
230  uiCmdsForWorkers.clear();
231  std::vector<G4String>* cmdCopy = G4UImanager::GetUIpointer()->GetCommandStack();
232  for ( std::vector<G4String>::const_iterator it = cmdCopy->begin() ;
233  it != cmdCopy->end(); ++it )
234  uiCmdsForWorkers.push_back(*it);
235  cmdCopy->clear();
236  delete cmdCopy;
237 }
238 
239 std::vector<G4String> G4MTRunManager::GetCommandStack()
240 {
241  G4AutoLock l(&cmdHandlingMutex);
242  return uiCmdsForWorkers;
243 }
244 
246 {
247  //Now loop on requested number of workers
248  //This will also start the workers
249  //Currently we do not allow to change the
250  //number of threads: threads area created once
251  if ( threads.size() == 0 ) {
252  for ( G4int nw = 0 ; nw<nworkers; ++nw) {
253  //Create a new worker and remember it
254  G4WorkerThread* context = new G4WorkerThread;
255  context->SetNumberThreads(nworkers);
256  context->SetThreadId(nw);
258  threads.push_back(thread);
259  }
260  }
261  //Signal to threads they can start a new run
263 }
264 
265 
266 void G4MTRunManager::InitializeEventLoop(G4int n_event, const char* macroFile, G4int n_select)
267 {
269  numberOfEventToBeProcessed = n_event;
271 
272  if(!fakeRun)
273  {
274  nSeedsUsed = 0;
275  nSeedsFilled = 0;
276 
277  if(verboseLevel>0)
278  { timer->Start(); }
279 
280  n_select_msg = n_select;
281  if(macroFile!=0)
282  {
283  if(n_select_msg<0) n_select_msg = n_event;
284  msgText = "/control/execute ";
285  msgText += macroFile;
286  selectMacro = macroFile;
287  }
288  else
289  {
290  n_select_msg = -1;
291  selectMacro = "";
292  }
293 
294  //initialize seeds
295  //If user did not implement InitializeSeeds,
296  // use default: nSeedsPerEvent seeds per event
297  if( eventModuloDef > 0 )
298  {
301  {
303  if(eventModulo<1) eventModulo =1;
305  msgd << "Event modulo is reduced to " << eventModulo
306  << " to distribute events to all threads.";
307  G4Exception("G4MTRunManager::InitializeEventLoop()",
308  "Run10035", JustWarning, msgd);
309  }
310  }
311  else
312  {
313  eventModulo = int(std::sqrt(double(numberOfEventToBeProcessed/nworkers)));
314  if(eventModulo<1) eventModulo =1;
315  }
316  if ( InitializeSeeds(n_event) == false && n_event>0 )
317  {
320  {
321  case 0:
322  nSeedsFilled = n_event;
323  break;
324  case 1:
326  break;
327  case 2:
328  nSeedsFilled = n_event/eventModulo + 1;
329  break;
330  default:
332  msgd << "Parameter value <" << seedOncePerCommunication
333  << "> of seedOncePerCommunication is invalid. It is reset to 0." ;
334  G4Exception("G4MTRunManager::InitializeEventLoop()",
335  "Run10036", JustWarning, msgd);
336  seedOncePerCommunication = 0;
337  nSeedsFilled = n_event;
338  }
339 
340  // Generates up to nSeedsMax seed pairs only.
343  helper->Fill(randDbl,nSeedsFilled,n_event,nSeedsPerEvent);
344  }
345  }
346 
347  //Now initialize workers. Check if user defined a WorkerThreadInitialization
350 
351  //Prepare UI commands for threads
353 
354  //Start worker threads
356 
357  // We need a barrier here. Wait for workers to start event loop.
358  //This will return only when all workers have started processing events.
360 }
361 
363 {
365  G4int nFill = 0;
367  {
368  case 0:
370  break;
371  case 1:
372  nFill = nworkers - nSeedsFilled;
373  break;
374  case 2:
375  default:
376  nFill = (numberOfEventToBeProcessed - nSeedsFilled*eventModulo)/eventModulo + 1;
377  }
378  // Generates up to nSeedsMax seed pairs only.
379  if(nFill>nSeedsMax) nFill=nSeedsMax;
380  masterRNGEngine->flatArray(nSeedsPerEvent*nFill,randDbl);
381  helper->Refill(randDbl,nFill);
382  nSeedsFilled += nFill;
383 //G4cout<<"helper->Refill() for "<<nFill<<" events."<<G4endl;
384 }
385 
387 {
388  //Wait for all worker threads to have finished the run
389  //i.e. wait for them to return from RunTermination()
390  //This guarantee that userrunaction for workers has been called
391 
392  // Wait now for all threads to finish event-loop
394  //Now call base-class methof
397 }
398 
400 {
402  //Call base class stuff...
404 
405  masterWorlds.clear();
407  std::vector<G4VPhysicalVolume*>::iterator itrW
409  for(size_t iWorld=0;iWorld<nWorlds;iWorld++)
410  {
411  addWorld(iWorld,*itrW);
412  itrW++;
413  }
414 }
415 
417 {
418  userWorkerInitialization = userInit;
419 }
420 
422 {
424 }
425 
427 {
428  userActionInitialization = userInit;
430 }
431 
433 {
435  //Needed for MT, to be moved in kernel
436 }
437 
439 {
441 }
442 
444 {
445  G4RunManager::SetUserAction(userAction);
446  userAction->SetMaster();
447 }
448 
450 {
451  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
452  "For multi-threaded version, define G4VUserPrimaryGeneratorAction in G4VUserActionInitialization.");
453 }
454 
456 {
457  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
458  "For multi-threaded version, define G4UserEventAction in G4VUserActionInitialization.");
459 }
460 
462 {
463  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
464  "For multi-threaded version, define G4UserStackingAction in G4VUserActionInitialization.");
465 }
466 
468 {
469  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
470  "For multi-threaded version, define G4UserTrackingAction in G4VUserActionInitialization.");
471 }
472 
474 {
475  G4Exception("G4MTRunManager::SetUserAction()", "Run3011", FatalException,
476  "For multi-threaded version, define G4UserSteppingAction in G4VUserActionInitialization.");
477 }
478 
479 void G4MTRunManager::MergeScores(const G4ScoringManager* localScoringManager)
480 {
481  G4AutoLock l(&scorerMergerMutex);
482  if(masterScM) masterScM->Merge(localScoringManager);
483 }
484 
485 void G4MTRunManager::MergeRun(const G4Run* localRun)
486 {
487  G4AutoLock l(&runMergerMutex);
488  if(currentRun) currentRun->Merge(localRun);
489 }
490 
491 G4bool G4MTRunManager::SetUpAnEvent(G4Event* evt,long& s1,long& s2,long& s3,G4bool reseedRequired)
492 {
493  G4AutoLock l(&setUpEventMutex);
495  {
497  if(reseedRequired)
498  {
500  G4int idx_rndm = nSeedsPerEvent*nSeedsUsed;
501  s1 = helper->GetSeed(idx_rndm);
502  s2 = helper->GetSeed(idx_rndm+1);
503  if(nSeedsPerEvent==3) s3 = helper->GetSeed(idx_rndm+2);
504  nSeedsUsed++;
505  if(nSeedsUsed==nSeedsFilled) RefillSeeds();
506  }
508  return true;
509  }
510  return false;
511 }
512 
514 {
515  G4AutoLock l(&setUpEventMutex);
517  {
518  G4int nev = eventModulo;
522  if(reseedRequired)
523  {
525  G4int nevRnd = nev;
526  if(seedOncePerCommunication>0) nevRnd = 1;
527  for(int i=0;i<nevRnd;i++)
528  {
529  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed));
530  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed+1));
531  if(nSeedsPerEvent==3)
532  seedsQueue->push(helper->GetSeed(nSeedsPerEvent*nSeedsUsed+2));
533  nSeedsUsed++;
534  if(nSeedsUsed==nSeedsFilled) RefillSeeds();
535  }
536  }
537  numberOfEventProcessed += nev;
538  return nev;
539  }
540  return 0;
541 }
542 
544 {
546  //Now join threads.
547 #ifdef G4MULTITHREADED //protect here to prevent warning in compilation
548  while ( ! threads.empty() )
549  {
550  G4Thread* t = * ( threads.begin() );
551  threads.pop_front();
553  //G4THREADJOIN(*t);
554  delete t;
555  }
556 #endif
557  threads.clear();
558 }
559 
560 #include "G4IonTable.hh"
561 #include "G4ParticleTable.hh"
562 #include "G4CascadeInterface.hh"
563 
565 {
567  //BERTINI, this is needed to create pseudo-particles, to be removed
569 }
570 
572 {
573  // This method is valid only for GeomClosed or EventProc state
574  G4ApplicationState currentState =
576  if(currentState==G4State_GeomClosed || currentState==G4State_EventProc)
577  {
578  runAborted = true;
579  MTkernel->BroadcastAbortRun(softAbort);
580  }
581  else
582  {
583  G4cerr << "Run is not in progress. AbortRun() ignored." << G4endl;
584  }
585 }
586 
588 {
589  // nothing to do in the master thread
590 }
591 
592 // =====================================
593 // Barriers mechanism
594 // =====================================
595 // We want to implement barriers.
596 // We define a barrier has a point in which threads synchronize.
597 // When workers threads reach a barrier they wait for the master thread a
598 // signal that they can continue. The master thread broadcast this signal
599 // only when all worker threads have reached this point.
600 // Currently only three points require this sync in the life-time of a G4 applicattion:
601 // Just before and just after the for-loop controlling the thread event-loop.
602 // Between runs.
603 // TODO: If this mechanism is needed in other parts of the code we can provide
604 // the barrier mechanism as a utility class/functions to the kernel.
605 // Note: we need a special treatment for WIN32
606 //
607 // The basic algorith of each barrier works like this:
608 // In the master:
609 // WaitWorkers() {
610 // while (true)
611 // {
612 // G4AutoLock l(&counterMutex); || Mutex is locked (1)
613 // if ( counter == nActiveThreads ) break;
614 // G4CONDITIONWAIT( &conditionOnCounter, &counterMutex); || Mutex is atomically released and wait, upon return locked (2)
615 // } || unlock mutex
616 // G4AutoLock l(&counterMutex); || lock again mutex (3)
617 // G4CONDITIONBROADCAST( &doSomethingCanStart ); || Here mutex is locked (4)
618 // } || final unlock (5)
619 // In the workers:
620 // WaitSignalFromMaster() {
621 // G4AutoLock l(&counterMutex); || (6)
622 // ++counter;
623 // G4CONDITIONBROADCAST(&conditionOnCounter); || (7)
624 // G4CONDITIONWAIT( &doSomethingCanStart , &counterMutex);|| (8)
625 // }
626 // Each barriers requires 2 conditions and one mutex, plus a counter.
627 // Important note: the thread calling broadcast should hold the mutex
628 // before calling broadcast to obtain predictible behavior
629 // http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_cond_broadcast.html
630 // Also remember that the wait for condition will atomically release the mutex
631 // and wait on condition, but it will lock again on mutex when returning
632 // Here it is how the control flows.
633 // Imagine master starts and only one worker (nActiveThreads==1)
634 // Master | Worker | counter | Who holds mutex
635 // Gets to (1) | Blocks on (6) | 0 | M
636 // Waits in (2) | | 0 | -
637 // | Arrives to (7) | 1 | W
638 // | Waits in (8) | 1 | -
639 // Gets to (1) | | 1 | M
640 // Jumps to (3) | | 1 | M
641 // End | | 1 | -
642 // | End | 1 | -
643 // Similarly for more than one worker threads or if worker starts
644 
645 #ifdef WIN32
646 #include <windows.h> //For CRITICAL_SECTION objects
647 #endif
648 namespace {
649  //Avoid compilation warning if squenetial for unused variables
650 #ifdef G4MULTITHREADED
651  //Conditions
652  // Condition to signal green light for start of event loop
653  G4Condition beginEventLoopCondition = G4CONDITION_INITIALIZER;
654  // Condition to signal green light to finish event loop
655  // (actuallyt exit function performing event loop)
656  G4Condition endEventLoopCondition = G4CONDITION_INITIALIZER;
657  // Condition to signal the num of workers ready for event loop has changed
658  G4Condition numWorkersBeginEventLoopChangeCondition = G4CONDITION_INITIALIZER;
659  // Condition to signal the num of workers that terminated event loop
660  // has changed
661  G4Condition numWorkersEndEventLoopChangedCondition = G4CONDITION_INITIALIZER;
662  // This condition is to handle more than one run w/o killing threads
663  G4Condition requestChangeActionForWorker = G4CONDITION_INITIALIZER;
664  G4Condition numberOfReadyWorkersForNewActionChangedCondition = G4CONDITION_INITIALIZER;
665 #endif
666  // Counter/mutex for workers ready to begin event loop
667  G4Mutex numberOfReadyWorkersMutex = G4MUTEX_INITIALIZER;
668  G4int numberOfReadyWorkers = 0;
669  //Counter/mutex for workers with end of event loop
670  G4Mutex numberOfEndOfEventLoopWorkersMutex = G4MUTEX_INITIALIZER;
671  G4int numberOfEndOfEventLoopWorkers = 0;
672  //
673  //Action handling
674  G4Mutex nextActionRequestMutex = G4MUTEX_INITIALIZER;
675  G4int numberOfReadyWorkersForNewAction = 0;
676  G4Mutex numberOfReadyWorkersForNewActionMutex = G4MUTEX_INITIALIZER;
677 #ifdef WIN32
678  CRITICAL_SECTION cs1;
679  CRITICAL_SECTION cs2;
680  CRITICAL_SECTION cs3;
681  //Note we need to use two separate counters because
682  //we can get a situation in which a thread is much faster then the others
683  //(for example if last thread has less events to process.
684  //We have the extreme case of some medical applications (moving setups)
685  //in which the number of events of a run is ~ number of threads
686  void InitializeWindowsConditions()
687  {
688  #ifdef G4MULTITHREADED
689  InitializeConditionVariable( &beginEventLoopCondition );
690  InitializeConditionVariable( &endEventLoopCondition );
691  InitializeConditionVariable( &numWorkersBeginEventLoopChangeCondition );
692  InitializeConditionVariable( &numWorkersEndEventLoopChangedCondition );
693  InitializeConditionVariable( &requestChangeActionForWorker);
694  InitializeConditionVariable( &numberOfReadyWorkersForNewActionChangedCondition );
695  #endif
696  InitializeCriticalSection( &cs1 );
697  InitializeCriticalSection( &cs2 );
698  InitializeCriticalSection( &cs3 );
699  }
700 #endif
701 }
702 
704 {
705  while (true) //begin barrier
706  {
707 #ifndef WIN32
708  G4AutoLock lockLoop(&numberOfReadyWorkersMutex);
709 #else
710  EnterCriticalSection( &cs1 );
711 #endif
712  //Check number of workers ready to begin
713  G4int activethreads = threads.size();
714  if (numberOfReadyWorkers == activethreads )
715  {
716  //Ok, interrupt the loop
717  break;
718  }
719  //Wait for the number of workers to be changed
720 #ifdef WIN32
721  G4CONDITIONWAIT(&numWorkersBeginEventLoopChangeCondition,
722  &cs1);
723  LeaveCriticalSection( &cs1 );
724 #else
725  G4CONDITIONWAIT(&numWorkersBeginEventLoopChangeCondition,
726  &numberOfReadyWorkersMutex);
727 #endif
728  }
729  //Now number of workers is as expected.
748 
749  //Prepare to wait for workers to end eventloop
750  //Reset number of workers in "EndOfEventLoop"
751  G4AutoLock l(&numberOfEndOfEventLoopWorkersMutex);
752  numberOfEndOfEventLoopWorkers = 0;
753 
754  //signal workers they can start the event-loop
755  G4AutoLock l2(&numberOfReadyWorkersMutex);
756  G4CONDTIONBROADCAST(&beginEventLoopCondition);
757 }
758 
760 {
761  //Increament number of active worker by 1
762 #ifndef WIN32
763  G4AutoLock lockLoop(&numberOfReadyWorkersMutex);
764 #else
765  EnterCriticalSection( &cs1 );
766 #endif
767  ++numberOfReadyWorkers;
768  //Signal the number of workers has changed
769  G4CONDTIONBROADCAST(&numWorkersBeginEventLoopChangeCondition);
770  //Wait for condition to start eventloop
771 #ifdef WIN32
772  G4CONDITIONWAIT(&beginEventLoopCondition,&cs1);
773  LeaveCriticalSection( &cs1 );
774 #else
775  G4CONDITIONWAIT(&beginEventLoopCondition,&numberOfReadyWorkersMutex);
776 #endif
777  //Protects access to shared resource, guarantees we do not call this method
778  //while someone else is modifying its content (e.g. creating a new particle)
779  //G4PDefManager& pdm = const_cast<G4PDefManager&>(G4ParticleDefinition::GetSubInstanceManager());
780  //pdm.Lock();
781  //pdm.NewSubInstances();
782  //pdm.UnLock();
783  //const_cast<G4PDefManager&>(G4ParticleDefinition::GetSubInstanceManager()).NewSubInstances();
784  // I believe this is not necessary and safe to remove (Makoto)
785  //G4ParticleTable::GetParticleTable()->WorkerG4ParticleTable();
786 }
787 
788 
790 {
791  while (true)
792  {
793 #ifndef WIN32
794  G4AutoLock l(&numberOfEndOfEventLoopWorkersMutex);
795 #else
796  EnterCriticalSection( &cs2 );
797 #endif
798  G4int activethreads = threads.size();
799  if ( numberOfEndOfEventLoopWorkers == activethreads )
800  {
801  break;
802  }
803 #ifdef WIN32
804  G4CONDITIONWAIT(&numWorkersEndEventLoopChangedCondition,
805  &cs2);
806  LeaveCriticalSection( &cs2 );
807 #else
808  G4CONDITIONWAIT(&numWorkersEndEventLoopChangedCondition,
809  &numberOfEndOfEventLoopWorkersMutex);
810 #endif
811  }
812  //Now number of workers that reached end of event loop is as expected
813  //Reset number of workers in ready for work state so a new run can start
814  G4AutoLock l(&numberOfReadyWorkersMutex);
815  numberOfReadyWorkers = 0;
816  //Signal workers they can end event-loop
817  G4AutoLock l2(&numberOfEndOfEventLoopWorkersMutex);
818  G4CONDTIONBROADCAST(&endEventLoopCondition);
819 }
820 
822 {
823  //Increament number of workers in end of evnet loop by 1
824 #ifndef WIN32
825  G4AutoLock l(&numberOfEndOfEventLoopWorkersMutex);
826 #else
827  EnterCriticalSection( &cs2 );
828 #endif
829  ++numberOfEndOfEventLoopWorkers;
830  //Signale this number has changed
831  G4CONDTIONBROADCAST(&numWorkersEndEventLoopChangedCondition);
832  //Wait for condition to exit eventloop
833 #ifdef WIN32
834  G4CONDITIONWAIT(&endEventLoopCondition,&cs2);
835  LeaveCriticalSection( &cs2 );
836 #else
837  G4CONDITIONWAIT(&endEventLoopCondition,&numberOfEndOfEventLoopWorkersMutex);
838 #endif
839 }
840 
842 {
843  //Wait for all workers to be ready to accept a new action request
844  while (true)
845  {
846 #ifndef WIN32
847  G4AutoLock l(&numberOfReadyWorkersForNewActionMutex);
848 #else
849  EnterCriticalSection( &cs3 );
850 #endif
851  //Check the number of workers that are ready for next action
852  G4int activethreads = threads.size();
853  if ( numberOfReadyWorkersForNewAction == activethreads )
854  {
855  //Ok, exit the loop
856  break;
857  }
858  //Wait for the number of workers ready for new action to change
859 #ifdef WIN32
860  G4CONDITIONWAIT(&numberOfReadyWorkersForNewActionChangedCondition,
861  &cs3);
862  LeaveCriticalSection( &cs3 );
863 #else
864  G4CONDITIONWAIT(&numberOfReadyWorkersForNewActionChangedCondition,
865  &numberOfReadyWorkersForNewActionMutex);
866 #endif
867  }
868  //Now set the new action to the shared resource
869  G4AutoLock l(&nextActionRequestMutex);
870  nextActionRequest = newRequest;
871  l.unlock();
872  //Reset counter of workers ready-for-new-action in preparation of next call
873  G4AutoLock l2(&numberOfReadyWorkersForNewActionMutex);
874  numberOfReadyWorkersForNewAction = 0;
875  //l2.unlock(); //<----- This thread needs to have control on mutex associated
876  //to condition variable (report from valgrind --tool=drd)
877  //see: http://pic.dhe.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Fapis%2Fusers_73.htm
878  //Now signal all workers that there is a new action to be performed
879  G4CONDTIONBROADCAST(&requestChangeActionForWorker);
880 }
881 
883 {
884  //This worker is ready to receive a new action request,
885  //increment counter by 1
886  #ifndef WIN32
887  G4AutoLock l(&numberOfReadyWorkersForNewActionMutex);
888 #else
889  EnterCriticalSection( &cs3 );
890 #endif
891  ++numberOfReadyWorkersForNewAction;
892  //Singal the sahred resource has changed to the master
893  G4CONDTIONBROADCAST(&numberOfReadyWorkersForNewActionChangedCondition);
894  //Wait for condition that a new aciton is ready
895 #ifdef WIN32
896  G4CONDITIONWAIT(&requestChangeActionForWorker,&cs3);
897  LeaveCriticalSection( &cs3 );
898 #else
899  G4CONDITIONWAIT(&requestChangeActionForWorker,&numberOfReadyWorkersForNewActionMutex);
900 #endif
901  //Ok, if I am here it means that a new action has been requested by the master
902  //reads it value that is now read-only, so no mutex is needed, but you never know...
903  G4AutoLock l2(&nextActionRequestMutex);
905  return result;
906 }
907 
909 {
910  if ( n == 0 )
911  {
912  G4Exception("G4MTRunManager::SetPinAffinity",
913  "Run0035",FatalException,
914  "Pin affinity must be >0 or <0.");
915  }
916  pinAffinity = n;
917  return;
918 }
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()
virtual G4int SetUpNEvents(G4Event *, G4SeedsQueue *seedsQueue, G4bool reseedRequired=true)
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
static G4int seedOncePerCommunication
G4int n_select_msg
std::vector< G4String > uiCmdsForWorkers
void Fill(double *dbl, int nev, int nev_tot, int nrpe)
Definition: G4RNGHelper.hh:96
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:192
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:78
virtual void InitializePhysics()
void SetThreadId(G4int threadId)
G4String msgText
int G4int
Definition: G4Types.hh:78
#define G4CONDITIONWAIT(cond, mutex)
Definition: G4Threading.hh:191
G4bool runAborted
std::vector< G4String > * GetCommandStack()
Definition: G4UImanager.cc:695
virtual void SetUserAction(G4UserRunAction *userAction)
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:175
std::queue< long > G4SeedsQueue
Definition: G4RNGHelper.hh:134
G4int G4Thread
Definition: G4Threading.hh:174
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:107
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()
static G4MTRunManager * GetMasterRunManager()
G4int G4GetNumberOfCores()
Definition: G4Threading.cc:126
void SetPinAffinity(G4int n=1)
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:173
virtual void Initialize()
G4String selectMacro
virtual void ThisWorkerReady()
virtual void AbortEvent()
void SetRunIDCounter(G4int i)
virtual G4bool SetUpAnEvent(G4Event *, long &s1, long &s2, long &s3, G4bool reseedRequired=true)
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:115
CLHEP::HepRandomEngine * masterRNGEngine
G4int G4Condition
Definition: G4Threading.hh:189
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:190
static G4MTRunManager * fMasterRM