|
||||
File indexing completed on 2025-01-18 09:58:42
0001 // 0002 // ******************************************************************** 0003 // * License and Disclaimer * 0004 // * * 0005 // * The Geant4 software is copyright of the Copyright Holders of * 0006 // * the Geant4 Collaboration. It is provided under the terms and * 0007 // * conditions of the Geant4 Software License, included in the file * 0008 // * LICENSE and available at http://cern.ch/geant4/license . These * 0009 // * include a list of copyright holders. * 0010 // * * 0011 // * Neither the authors of this software system, nor their employing * 0012 // * institutes,nor the agencies providing financial support for this * 0013 // * work make any representation or warranty, express or implied, * 0014 // * regarding this software system or assume any liability for its * 0015 // * use. Please see the license in the file LICENSE and URL above * 0016 // * for the full disclaimer and the limitation of liability. * 0017 // * * 0018 // * This code implementation is the result of the scientific and * 0019 // * technical work of the GEANT4 collaboration. * 0020 // * By using, copying, modifying or distributing the software (or * 0021 // * any work based on the software) you agree to acknowledge its * 0022 // * use in resulting scientific publications, and indicate your * 0023 // * acceptance of all terms of the Geant4 Software license. * 0024 // ******************************************************************** 0025 // 0026 // G4MTBarrier 0027 // 0028 // Class description: 0029 // 0030 // This class defines a synchronization point between threads: a master 0031 // and a pool of workers. 0032 // A barrier is a (shared) instance of this class. Master sets the number 0033 // of active threads to wait for, then it waits for workers to become ready 0034 // calling the method WaitForReadyWorkers(). 0035 // The master thread will block on this call. 0036 // Each of the workers calls ThisWorkerReady() when it is ready to continue. 0037 // It will block on this call. 0038 // When all worker threads have called ThisWorkerReady and are waiting the 0039 // master will release the barrier and execution will continue. 0040 // 0041 // User code can implement more advanced barriers that require exchange 0042 // of a message between master and threads inheriting from this class as in: 0043 // class Derived : public G4MTBarrier { 0044 // G4Mutex mutexForMessage; 0045 // SomeType message; 0046 // void MethodCalledByWorkers() { 0047 // G4MTBarrirer::ThisWorkerReady(); 0048 // G4AutoLock l(&mutexForMessage); 0049 // [... process message ...] 0050 // } 0051 // void WaitForReadyWorkers() override { 0052 // Wait(); <== Mandatory 0053 // [.. process message ...] <== User code between the two calls 0054 // ReleaseBarrier(); <== Mandatory 0055 // } 0056 // void MethodCalledByMaster() { WaitForReadyWorkers(); } 0057 // } 0058 // User code can also achieve the same results as before using the granular 0059 // methods LoopWaitingWorkers and ResetCounterAndBroadcast methods in the 0060 // master. For examples of usage of this class see G4MTRunManager 0061 // 0062 // ===================================== 0063 // Barriers mechanism 0064 // ===================================== 0065 // We define a barrier has a point in which threads synchronize. 0066 // When workers threads reach a barrier they wait for the master thread a 0067 // signal that they can continue. The master thread broadcast this signal 0068 // only when all worker threads have reached this point. 0069 // Currently only three points require this sync in the life-time of a G4 0070 // application: just before and just after the for-loop controlling the 0071 // thread event-loop and between runs. 0072 // 0073 // The basic algorithm of each barrier works like this: 0074 // In the master: 0075 // WaitWorkers() 0076 // { 0077 // while (true) 0078 // { 0079 // G4AutoLock l(&counterMutex); || Mutex is locked 0080 // (1) if ( counter == nActiveThreads ) break; G4CONDITIONWAIT( 0081 // &conditionOnCounter, &counterMutex); || Mutex is atomically released and 0082 // wait, upon return locked (2) 0083 // } || unlock mutex 0084 // G4AutoLock l(&counterMutex); || lock again mutex 0085 // (3) G4CONDITIONBROADCAST( &doSomethingCanStart ); || Here mutex 0086 // is locked (4) 0087 // } || final unlock (5) 0088 // In the workers: 0089 // WaitSignalFromMaster() 0090 // { 0091 // G4AutoLock l(&counterMutex); || (6) 0092 // ++counter; 0093 // G4CONDITIONBROADCAST(&conditionOnCounter); || (7) 0094 // G4CONDITIONWAIT( &doSomethingCanStart , &counterMutex);|| (8) 0095 // } 0096 // Each barrier requires 2 conditions and one mutex, plus a counter. 0097 // Important note: the thread calling broadcast should hold the mutex 0098 // before calling broadcast to obtain predictible behavior 0099 // http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_cond_broadcast.html 0100 // Also remember that the wait for condition will atomically release the mutex 0101 // and wait on condition, but it will lock again on mutex when returning 0102 // Here it is how the control flows. 0103 // Imagine master starts and only one worker (nActiveThreads==1) 0104 // Master | Worker | counter | Who holds mutex 0105 // Gets to (1) | Blocks on (6) | 0 | M 0106 // Waits in (2) | | 0 | - 0107 // | Arrives to (7) | 1 | W 0108 // | Waits in (8) | 1 | - 0109 // Gets to (1) | | 1 | M 0110 // Jumps to (3) | | 1 | M 0111 // End | | 1 | - 0112 // | End | 1 | - 0113 // Similarly for more than one worker threads or if worker starts 0114 0115 // Author: A.Dotti (SLAC), 10 February 2016 0116 // -------------------------------------------------------------------- 0117 #ifndef G4MTBARRIER_HH 0118 #define G4MTBARRIER_HH 0119 0120 #include "G4Threading.hh" 0121 0122 class G4MTBarrier 0123 { 0124 public: 0125 G4MTBarrier() 0126 : G4MTBarrier(1) 0127 {} 0128 virtual ~G4MTBarrier() {} 0129 G4MTBarrier(const G4MTBarrier&) = delete; 0130 G4MTBarrier& operator=(const G4MTBarrier&) = delete; 0131 0132 // on explicitly defaulted move at 0133 // https://msdn.microsoft.com/en-us/library/dn457344.aspx 0134 // G4MTBarrier(G4MTBarrier&&) = default; 0135 // G4MTBarrier& operator=(G4MTBarrier&&) = default; 0136 0137 G4MTBarrier(unsigned int numThreads); 0138 void ThisWorkerReady(); 0139 virtual void WaitForReadyWorkers(); 0140 inline void SetActiveThreads(unsigned int val) { m_numActiveThreads = val; } 0141 void ResetCounter(); 0142 unsigned int GetCounter(); 0143 void Wait(); 0144 void ReleaseBarrier(); 0145 inline void Wait(unsigned int numt) 0146 { 0147 SetActiveThreads(numt); 0148 Wait(); 0149 } 0150 0151 private: 0152 unsigned int m_numActiveThreads = 0; 0153 unsigned int m_counter = 0; 0154 G4Mutex m_mutex; 0155 G4Condition m_counterChanged; 0156 G4Condition m_continue; 0157 }; 0158 0159 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |