Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/global/management/include/G4MTBarrier.hh

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 
122 class G4MTBarrier
123 {
124  public:
125   G4MTBarrier()
126     : G4MTBarrier(1)
127   {}
128   virtual ~G4MTBarrier() {}
129   G4MTBarrier(const G4MTBarrier&) = delete;
130   G4MTBarrier& operator=(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
160