Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4MTBarrier.hh
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// G4MTBarrier
27//
28// Class description:
29//
30// This class defines a synchronization point between threads: a master
31// and a pool of workers.
32// A barrier is a (shared) instance of this class. Master sets the number
33// of active threads to wait for, then it waits for workers to become ready
34// calling the method WaitForReadyWorkers().
35// The master thread will block on this call.
36// Each of the workers calls ThisWorkerReady() when it is ready to continue.
37// It will block on this call.
38// When all worker threads have called ThisWorkerReady and are waiting the
39// master will release the barrier and execution will continue.
40//
41// User code can implement more advanced barriers that require exchange
42// of a message between master and threads inheriting from this class as in:
43// class Derived : public G4MTBarrier {
44// G4Mutex mutexForMessage;
45// SomeType message;
46// void MethodCalledByWorkers() {
47// G4MTBarrirer::ThisWorkerReady();
48// G4AutoLock l(&mutexForMessage);
49// [... process message ...]
50// }
51// void WaitForReadyWorkers() override {
52// Wait(); <== Mandatory
53// [.. process message ...] <== User code between the two calls
54// ReleaseBarrier(); <== Mandatory
55// }
56// void MethodCalledByMaster() { WaitForReadyWorkers(); }
57// }
58// User code can also achieve the same results as before using the granular
59// methods LoopWaitingWorkers and ResetCounterAndBroadcast methods in the
60// master. For examples of usage of this class see G4MTRunManager
61//
62// =====================================
63// Barriers mechanism
64// =====================================
65// We define a barrier has a point in which threads synchronize.
66// When workers threads reach a barrier they wait for the master thread a
67// signal that they can continue. The master thread broadcast this signal
68// only when all worker threads have reached this point.
69// Currently only three points require this sync in the life-time of a G4
70// application: just before and just after the for-loop controlling the
71// thread event-loop and between runs.
72//
73// The basic algorithm of each barrier works like this:
74// In the master:
75// WaitWorkers()
76// {
77// while (true)
78// {
79// G4AutoLock l(&counterMutex); || Mutex is locked
80// (1) if ( counter == nActiveThreads ) break; G4CONDITIONWAIT(
81// &conditionOnCounter, &counterMutex); || Mutex is atomically released and
82// wait, upon return locked (2)
83// } || unlock mutex
84// G4AutoLock l(&counterMutex); || lock again mutex
85// (3) G4CONDITIONBROADCAST( &doSomethingCanStart ); || Here mutex
86// is locked (4)
87// } || final unlock (5)
88// In the workers:
89// WaitSignalFromMaster()
90// {
91// G4AutoLock l(&counterMutex); || (6)
92// ++counter;
93// G4CONDITIONBROADCAST(&conditionOnCounter); || (7)
94// G4CONDITIONWAIT( &doSomethingCanStart , &counterMutex);|| (8)
95// }
96// Each barrier requires 2 conditions and one mutex, plus a counter.
97// Important note: the thread calling broadcast should hold the mutex
98// before calling broadcast to obtain predictible behavior
99// http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_cond_broadcast.html
100// Also remember that the wait for condition will atomically release the mutex
101// and wait on condition, but it will lock again on mutex when returning
102// Here it is how the control flows.
103// Imagine master starts and only one worker (nActiveThreads==1)
104// Master | Worker | counter | Who holds mutex
105// Gets to (1) | Blocks on (6) | 0 | M
106// Waits in (2) | | 0 | -
107// | Arrives to (7) | 1 | W
108// | Waits in (8) | 1 | -
109// Gets to (1) | | 1 | M
110// Jumps to (3) | | 1 | M
111// End | | 1 | -
112// | End | 1 | -
113// Similarly for more than one worker threads or if worker starts
114
115// Author: A.Dotti (SLAC), 10 February 2016
116// --------------------------------------------------------------------
117#ifndef G4MTBARRIER_HH
118#define G4MTBARRIER_HH
119
120#include "G4Threading.hh"
121
123{
124 public:
126 : G4MTBarrier(1)
127 {}
128 virtual ~G4MTBarrier() {}
129 G4MTBarrier(const G4MTBarrier&) = delete;
131
132 // on explicitly defaulted move at
133 // https://msdn.microsoft.com/en-us/library/dn457344.aspx
134 // G4MTBarrier(G4MTBarrier&&) = default;
135 // G4MTBarrier& operator=(G4MTBarrier&&) = default;
136
137 G4MTBarrier(unsigned int numThreads);
138 void ThisWorkerReady();
139 virtual void WaitForReadyWorkers();
140 inline void SetActiveThreads(unsigned int val) { m_numActiveThreads = val; }
141 void ResetCounter();
142 unsigned int GetCounter();
143 void Wait();
144 void ReleaseBarrier();
145 inline void Wait(unsigned int numt)
146 {
147 SetActiveThreads(numt);
148 Wait();
149 }
150
151 private:
152 unsigned int m_numActiveThreads = 0;
153 unsigned int m_counter = 0;
154 G4Mutex m_mutex;
155 G4Condition m_counterChanged;
156 G4Condition m_continue;
157};
158
159#endif
G4int G4Condition
Definition: G4Threading.hh:273
std::mutex G4Mutex
Definition: G4Threading.hh:81
void Wait(unsigned int numt)
Definition: G4MTBarrier.hh:145
void ThisWorkerReady()
Definition: G4MTBarrier.cc:40
virtual ~G4MTBarrier()
Definition: G4MTBarrier.hh:128
void ResetCounter()
Definition: G4MTBarrier.cc:90
G4MTBarrier(const G4MTBarrier &)=delete
void Wait()
Definition: G4MTBarrier.cc:53
virtual void WaitForReadyWorkers()
Definition: G4MTBarrier.cc:81
void ReleaseBarrier()
Definition: G4MTBarrier.cc:72
void SetActiveThreads(unsigned int val)
Definition: G4MTBarrier.hh:140
G4MTBarrier & operator=(const G4MTBarrier &)=delete
unsigned int GetCounter()
Definition: G4MTBarrier.cc:97