Geant4 Cross Reference |
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 // G4GeomSplitter 27 // 28 // Class description: 29 // 30 // Utility template class for splitting of RW data for thread-safety from 31 // classes: G4LogicalVolume, G4Region, G4VPhysicalVolume, G4PolyconeSide 32 // G4PolyhedraSide, G4PVReplica. 33 34 // Author: X.Dong - Initial version from automatic MT conversion, 01.25.09. 35 // ------------------------------------------------------------------------ 36 #ifndef G4GEOMSPLITTER_HH 37 #define G4GEOMSPLITTER_HH 38 39 #include "globals.hh" 40 #include "geomwdefs.hh" 41 #include "G4AutoLock.hh" 42 43 template <class T> // T is the private data from the object to be split 44 class G4GeomSplitter 45 { 46 public: 47 48 G4GeomSplitter() 49 : sharedOffset(nullptr) 50 { 51 G4MUTEXINIT(mutex); 52 } 53 54 T* Reallocate(G4int size) 55 { 56 totalspace = size; 57 return (T *) std::realloc(offset, totalspace * sizeof(T)); 58 } 59 60 G4int CreateSubInstance() 61 // Invoked by the master or work thread to create a new subinstance 62 // whenever a new split class instance is created. 63 { 64 G4AutoLock l(&mutex); 65 ++totalobj; 66 if (totalobj > totalspace) 67 { 68 offset = Reallocate(totalspace+512); 69 if (offset == nullptr) 70 { 71 G4Exception("G4GeomSPlitter::CreateSubInstance()", 72 "OutOfMemory", FatalException, "Cannot malloc space!"); 73 } 74 sharedOffset = offset; 75 } 76 return (totalobj - 1); 77 } 78 79 void CopyMasterContents() 80 { 81 G4AutoLock l(&mutex); 82 std::memcpy(offset, sharedOffset, totalspace * sizeof(T)); 83 } 84 85 void SlaveCopySubInstanceArray() 86 // Invoked by each worker thread to copy all the subinstance array 87 // from the master thread. 88 { 89 G4AutoLock l(&mutex); 90 if (offset != nullptr) { return; } 91 offset = Reallocate(totalspace); 92 if (offset == nullptr) 93 { 94 G4Exception("G4GeomSplitter::SlaveCopySubInstanceArray()", 95 "OutOfMemory", FatalException, "Cannot malloc space!"); 96 } 97 l.unlock(); 98 CopyMasterContents(); 99 } 100 101 void SlaveInitializeSubInstance() 102 // Invoked by each worker thread to create the subinstance array and 103 // initialize each subinstance using a particular method defined by 104 // the subclass. 105 { 106 G4AutoLock l(&mutex); 107 if (offset != nullptr) { return; } 108 offset = Reallocate(totalspace); 109 110 if (offset == nullptr) 111 { 112 G4Exception("G4GeomSplitter::SlaveInitializeSubInstance()", 113 "OutOfMemory", FatalException, "Cannot malloc space!"); 114 } 115 116 for (G4int i=0 ; i<totalspace; ++i) 117 { 118 offset[i].initialize(); 119 } 120 } 121 122 void SlaveReCopySubInstanceArray() 123 // Invoked by each worker thread at start of a run (2nd or later) 124 // to copy again all the subinstance array from the master thread. 125 // To cope with user's changes in Geometry - e.g. change of material 126 // in a volume 127 { 128 if (offset == nullptr) 129 { 130 SlaveInitializeSubInstance(); 131 G4Exception("G4GeomSPlitter::SlaveReCopySubInstance()", 132 "MissingInitialisation", JustWarning, 133 "Must be called after Initialisation or first Copy."); 134 } 135 CopyMasterContents(); 136 } 137 138 void FreeSlave() 139 // Invoked by all threads to free the subinstance array. 140 { 141 if (offset == nullptr) { return; } 142 std::free( offset ); 143 offset = nullptr; 144 } 145 146 // Extension - to allow sharing of workspaces 147 148 T* GetOffset() { return offset; } 149 150 void UseWorkArea( T* newOffset ) 151 // Use recycled work area - which was created previously 152 { 153 if( (offset!=nullptr) && (offset!=newOffset) ) 154 { 155 G4Exception("G4GeomSplitter::UseWorkspace()", 156 "TwoWorkspaces", FatalException, 157 "Thread already has workspace - cannot use another."); 158 } 159 offset= newOffset; 160 } 161 162 T* FreeWorkArea() 163 // Detach this thread from this Location. 164 // The object which calls this method is responsible for it. 165 { 166 T* offsetRet = offset; 167 offset = nullptr; 168 return offsetRet; 169 } 170 171 public: 172 173 G4GEOM_DLL static G4ThreadLocal T* offset; 174 175 private: 176 177 G4int totalobj{0}; 178 G4int totalspace{0}; 179 T* sharedOffset; 180 G4Mutex mutex; 181 }; 182 183 template <typename T> G4ThreadLocal T* G4GeomSplitter<T>::offset = nullptr; 184 185 #endif 186