Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // G4GeomSplitter 26 // G4GeomSplitter 27 // 27 // 28 // Class description: 28 // Class description: 29 // 29 // 30 // Utility template class for splitting of RW 30 // Utility template class for splitting of RW data for thread-safety from 31 // classes: G4LogicalVolume, G4Region, G4VPhys 31 // classes: G4LogicalVolume, G4Region, G4VPhysicalVolume, G4PolyconeSide 32 // G4PolyhedraSide, G4PVReplica. 32 // G4PolyhedraSide, G4PVReplica. 33 33 34 // Author: X.Dong - Initial version from autom 34 // Author: X.Dong - Initial version from automatic MT conversion, 01.25.09. 35 // ------------------------------------------- 35 // ------------------------------------------------------------------------ 36 #ifndef G4GEOMSPLITTER_HH 36 #ifndef G4GEOMSPLITTER_HH 37 #define G4GEOMSPLITTER_HH 37 #define G4GEOMSPLITTER_HH 38 38 39 #include "globals.hh" 39 #include "globals.hh" 40 #include "geomwdefs.hh" 40 #include "geomwdefs.hh" 41 #include "G4AutoLock.hh" 41 #include "G4AutoLock.hh" 42 42 43 template <class T> // T is the private data f 43 template <class T> // T is the private data from the object to be split 44 class G4GeomSplitter 44 class G4GeomSplitter 45 { 45 { 46 public: 46 public: 47 47 48 G4GeomSplitter() 48 G4GeomSplitter() 49 : sharedOffset(nullptr) << 49 : totalobj(0), totalspace(0), sharedOffset(nullptr) 50 { 50 { 51 G4MUTEXINIT(mutex); 51 G4MUTEXINIT(mutex); 52 } 52 } 53 53 54 T* Reallocate(G4int size) 54 T* Reallocate(G4int size) 55 { 55 { 56 totalspace = size; 56 totalspace = size; 57 return (T *) std::realloc(offset, total 57 return (T *) std::realloc(offset, totalspace * sizeof(T)); 58 } 58 } 59 59 60 G4int CreateSubInstance() 60 G4int CreateSubInstance() 61 // Invoked by the master or work thread 61 // Invoked by the master or work thread to create a new subinstance 62 // whenever a new split class instance i 62 // whenever a new split class instance is created. 63 { 63 { 64 G4AutoLock l(&mutex); 64 G4AutoLock l(&mutex); 65 ++totalobj; 65 ++totalobj; 66 if (totalobj > totalspace) 66 if (totalobj > totalspace) 67 { 67 { 68 offset = Reallocate(totalspace+512); 68 offset = Reallocate(totalspace+512); 69 if (offset == nullptr) 69 if (offset == nullptr) 70 { 70 { 71 G4Exception("G4GeomSPlitter::Create 71 G4Exception("G4GeomSPlitter::CreateSubInstance()", 72 "OutOfMemory", FatalExc 72 "OutOfMemory", FatalException, "Cannot malloc space!"); 73 } 73 } 74 sharedOffset = offset; 74 sharedOffset = offset; 75 } 75 } 76 return (totalobj - 1); 76 return (totalobj - 1); 77 } 77 } 78 78 79 void CopyMasterContents() 79 void CopyMasterContents() 80 { 80 { 81 G4AutoLock l(&mutex); 81 G4AutoLock l(&mutex); 82 std::memcpy(offset, sharedOffset, totals 82 std::memcpy(offset, sharedOffset, totalspace * sizeof(T)); 83 } 83 } 84 84 85 void SlaveCopySubInstanceArray() 85 void SlaveCopySubInstanceArray() 86 // Invoked by each worker thread to copy 86 // Invoked by each worker thread to copy all the subinstance array 87 // from the master thread. 87 // from the master thread. 88 { 88 { 89 G4AutoLock l(&mutex); 89 G4AutoLock l(&mutex); 90 if (offset != nullptr) { return; } 90 if (offset != nullptr) { return; } 91 offset = Reallocate(totalspace); 91 offset = Reallocate(totalspace); 92 if (offset == nullptr) 92 if (offset == nullptr) 93 { 93 { 94 G4Exception("G4GeomSplitter::SlaveCopy 94 G4Exception("G4GeomSplitter::SlaveCopySubInstanceArray()", 95 "OutOfMemory", FatalExcept 95 "OutOfMemory", FatalException, "Cannot malloc space!"); 96 } 96 } 97 l.unlock(); 97 l.unlock(); 98 CopyMasterContents(); 98 CopyMasterContents(); 99 } 99 } 100 100 101 void SlaveInitializeSubInstance() 101 void SlaveInitializeSubInstance() 102 // Invoked by each worker thread to crea 102 // Invoked by each worker thread to create the subinstance array and 103 // initialize each subinstance using a p 103 // initialize each subinstance using a particular method defined by 104 // the subclass. 104 // the subclass. 105 { 105 { 106 G4AutoLock l(&mutex); 106 G4AutoLock l(&mutex); 107 if (offset != nullptr) { return; } 107 if (offset != nullptr) { return; } 108 offset = Reallocate(totalspace); 108 offset = Reallocate(totalspace); 109 109 110 if (offset == nullptr) 110 if (offset == nullptr) 111 { 111 { 112 G4Exception("G4GeomSplitter::SlaveInit 112 G4Exception("G4GeomSplitter::SlaveInitializeSubInstance()", 113 "OutOfMemory", FatalExcept 113 "OutOfMemory", FatalException, "Cannot malloc space!"); 114 } 114 } 115 115 116 for (G4int i=0 ; i<totalspace; ++i) 116 for (G4int i=0 ; i<totalspace; ++i) 117 { 117 { 118 offset[i].initialize(); 118 offset[i].initialize(); 119 } 119 } 120 } 120 } 121 121 122 void SlaveReCopySubInstanceArray() 122 void SlaveReCopySubInstanceArray() 123 // Invoked by each worker thread at star 123 // Invoked by each worker thread at start of a run (2nd or later) 124 // to copy again all the subinstance arr 124 // to copy again all the subinstance array from the master thread. 125 // To cope with user's changes in Geomet 125 // To cope with user's changes in Geometry - e.g. change of material 126 // in a volume 126 // in a volume 127 { 127 { 128 if (offset == nullptr) 128 if (offset == nullptr) 129 { 129 { 130 SlaveInitializeSubInstance(); 130 SlaveInitializeSubInstance(); 131 G4Exception("G4GeomSPlitter::SlaveReCo 131 G4Exception("G4GeomSPlitter::SlaveReCopySubInstance()", 132 "MissingInitialisation", J 132 "MissingInitialisation", JustWarning, 133 "Must be called after Init 133 "Must be called after Initialisation or first Copy."); 134 } 134 } 135 CopyMasterContents(); 135 CopyMasterContents(); 136 } 136 } 137 137 138 void FreeSlave() 138 void FreeSlave() 139 // Invoked by all threads to free the su 139 // Invoked by all threads to free the subinstance array. 140 { 140 { 141 if (offset == nullptr) { return; } 141 if (offset == nullptr) { return; } 142 std::free( offset ); 142 std::free( offset ); 143 offset = nullptr; 143 offset = nullptr; 144 } 144 } 145 145 146 // Extension - to allow sharing of workspa 146 // Extension - to allow sharing of workspaces 147 147 148 T* GetOffset() { return offset; } 148 T* GetOffset() { return offset; } 149 149 150 void UseWorkArea( T* newOffset ) 150 void UseWorkArea( T* newOffset ) 151 // Use recycled work area - which was cr 151 // Use recycled work area - which was created previously 152 { 152 { 153 if( (offset!=nullptr) && (offset!=newOff 153 if( (offset!=nullptr) && (offset!=newOffset) ) 154 { 154 { 155 G4Exception("G4GeomSplitter::UseWorks 155 G4Exception("G4GeomSplitter::UseWorkspace()", 156 "TwoWorkspaces", FatalExc 156 "TwoWorkspaces", FatalException, 157 "Thread already has works 157 "Thread already has workspace - cannot use another."); 158 } 158 } 159 offset= newOffset; 159 offset= newOffset; 160 } 160 } 161 161 162 T* FreeWorkArea() 162 T* FreeWorkArea() 163 // Detach this thread from this Location 163 // Detach this thread from this Location. 164 // The object which calls this method is 164 // The object which calls this method is responsible for it. 165 { 165 { 166 T* offsetRet = offset; 166 T* offsetRet = offset; 167 offset = nullptr; 167 offset = nullptr; 168 return offsetRet; 168 return offsetRet; 169 } 169 } 170 170 171 public: 171 public: 172 172 173 G4GEOM_DLL static G4ThreadLocal T* offset; 173 G4GEOM_DLL static G4ThreadLocal T* offset; 174 174 175 private: 175 private: 176 176 177 G4int totalobj{0}; << 177 G4int totalobj; 178 G4int totalspace{0}; << 178 G4int totalspace; 179 T* sharedOffset; 179 T* sharedOffset; 180 G4Mutex mutex; 180 G4Mutex mutex; 181 }; 181 }; 182 182 183 template <typename T> G4ThreadLocal T* G4GeomS 183 template <typename T> G4ThreadLocal T* G4GeomSplitter<T>::offset = nullptr; 184 184 185 #endif 185 #endif 186 186