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 // G4LogicalVolumeStore implementation 27 // 28 // 10.07.95, P.Kent, G.Cosmo 29 // -------------------------------------------------------------------- 30 31 #include "G4Types.hh" 32 #include "G4LogicalVolumeStore.hh" 33 #include "G4GeometryManager.hh" 34 35 #include "G4AutoLock.hh" 36 37 namespace 38 { 39 G4Mutex mapMutex = G4MUTEX_INITIALIZER; 40 } 41 42 // *************************************************************************** 43 // Static class variables 44 // *************************************************************************** 45 // 46 G4LogicalVolumeStore* G4LogicalVolumeStore::fgInstance = nullptr; 47 G4ThreadLocal G4VStoreNotifier* G4LogicalVolumeStore::fgNotifier = nullptr; 48 G4ThreadLocal G4bool G4LogicalVolumeStore::locked = false; 49 50 // *************************************************************************** 51 // Protected constructor: Construct underlying container with 52 // initial size of 100 entries 53 // *************************************************************************** 54 // 55 G4LogicalVolumeStore::G4LogicalVolumeStore() 56 57 { 58 reserve(100); 59 } 60 61 // *************************************************************************** 62 // Destructor 63 // *************************************************************************** 64 // 65 G4LogicalVolumeStore::~G4LogicalVolumeStore() 66 { 67 Clean(); // Delete all volumes in the store 68 G4LogicalVolume::Clean(); // Delete allocated sub-instance data 69 } 70 71 // *************************************************************************** 72 // Delete all elements from the store 73 // *************************************************************************** 74 // 75 void G4LogicalVolumeStore::Clean() 76 { 77 // Do nothing if geometry is closed 78 // 79 if (G4GeometryManager::GetInstance()->IsGeometryClosed()) 80 { 81 G4cout << "WARNING - Attempt to delete the logical volume store" 82 << " while geometry closed !" << G4endl; 83 return; 84 } 85 86 // Locks store for deletion of volumes. De-registration will be 87 // performed at this stage. G4LogicalVolumes will not de-register themselves. 88 // 89 locked = true; 90 91 G4LogicalVolumeStore* store = GetInstance(); 92 93 for(auto pos=store->cbegin(); pos!=store->cend(); ++pos) 94 { 95 if (fgNotifier != nullptr) { fgNotifier->NotifyDeRegistration(); } 96 if (*pos != nullptr) { (*pos)->Lock(); delete *pos; } 97 } 98 99 store->bmap.clear(); store->mvalid = false; 100 locked = false; 101 store->clear(); 102 } 103 104 // *************************************************************************** 105 // Associate user notifier to the store 106 // *************************************************************************** 107 // 108 void G4LogicalVolumeStore::SetNotifier(G4VStoreNotifier* pNotifier) 109 { 110 GetInstance(); 111 fgNotifier = pNotifier; 112 } 113 114 // *************************************************************************** 115 // Bring contents of internal map up to date and reset validity flag 116 // *************************************************************************** 117 // 118 void G4LogicalVolumeStore::UpdateMap() 119 { 120 G4AutoLock l(&mapMutex); // to avoid thread contention at initialisation 121 if (mvalid) return; 122 bmap.clear(); 123 for(auto pos=GetInstance()->cbegin(); pos!=GetInstance()->cend(); ++pos) 124 { 125 const G4String& vol_name = (*pos)->GetName(); 126 auto it = bmap.find(vol_name); 127 if (it != bmap.cend()) 128 { 129 it->second.push_back(*pos); 130 } 131 else 132 { 133 std::vector<G4LogicalVolume*> vol_vec { *pos }; 134 bmap.insert(std::make_pair(vol_name, vol_vec)); 135 } 136 } 137 mvalid = true; 138 l.unlock(); 139 } 140 141 // *************************************************************************** 142 // Add volume to container 143 // *************************************************************************** 144 // 145 void G4LogicalVolumeStore::Register(G4LogicalVolume* pVolume) 146 { 147 G4LogicalVolumeStore* store = GetInstance(); 148 store->push_back(pVolume); 149 const G4String& vol_name = pVolume->GetName(); 150 auto it = store->bmap.find(vol_name); 151 if (it != store->bmap.cend()) 152 { 153 it->second.push_back(pVolume); 154 } 155 else 156 { 157 std::vector<G4LogicalVolume*> vol_vec { pVolume }; 158 store->bmap.insert(std::make_pair(vol_name, vol_vec)); 159 } 160 if (fgNotifier != nullptr) { fgNotifier->NotifyRegistration(); } 161 store->mvalid = true; 162 } 163 164 // *************************************************************************** 165 // Remove volume from container 166 // *************************************************************************** 167 // 168 void G4LogicalVolumeStore::DeRegister(G4LogicalVolume* pVolume) 169 { 170 G4LogicalVolumeStore* store = GetInstance(); 171 if (!locked) // Do not de-register if locked ! 172 { 173 if (fgNotifier != nullptr) { fgNotifier->NotifyDeRegistration(); } 174 for (auto i=store->cbegin(); i!=store->cend(); ++i) 175 { 176 if (**i==*pVolume) 177 { 178 store->erase(i); 179 break; 180 } 181 } 182 const G4String& vol_name = pVolume->GetName(); 183 auto it = store->bmap.find(vol_name); 184 if (it != store->bmap.cend()) 185 { 186 if (it->second.size() > 1) 187 { 188 for (auto i=it->second.cbegin(); i!=it->second.cend(); ++i) 189 { 190 if (**i==*pVolume) 191 { 192 it->second.erase(i); 193 break; 194 } 195 } 196 } 197 else 198 { 199 store->bmap.erase(it); 200 } 201 } 202 } 203 } 204 205 // *************************************************************************** 206 // Retrieve the first or last volume pointer in the container having that name 207 // *************************************************************************** 208 // 209 G4LogicalVolume* 210 G4LogicalVolumeStore::GetVolume(const G4String& name, G4bool verbose, 211 G4bool reverseSearch) const 212 { 213 G4LogicalVolumeStore* store = GetInstance(); 214 if (!store->mvalid) { store->UpdateMap(); } 215 auto pos = store->bmap.find(name); 216 if(pos != store->bmap.cend()) 217 { 218 if ((verbose) && (pos->second.size()>1)) 219 { 220 std::ostringstream message; 221 message << "There exists more than ONE logical volume in store named: " 222 << name << "!" << G4endl 223 << "Returning the first found."; 224 G4Exception("G4LogicalVolumeStore::GetVolume()", 225 "GeomMgt1001", JustWarning, message); 226 } 227 if(reverseSearch) 228 { 229 return pos->second[pos->second.size()-1]; 230 } 231 else 232 { 233 return pos->second[0]; 234 } 235 } 236 if (verbose) 237 { 238 std::ostringstream message; 239 message << "Volume NOT found in store !" << G4endl 240 << " Volume " << name << " NOT found in store !" << G4endl 241 << " Returning NULL pointer."; 242 G4Exception("G4LogicalVolumeStore::GetVolume()", 243 "GeomMgt1001", JustWarning, message); 244 } 245 return nullptr; 246 } 247 248 // *************************************************************************** 249 // Return ptr to Store, setting if necessary 250 // *************************************************************************** 251 // 252 G4LogicalVolumeStore* G4LogicalVolumeStore::GetInstance() 253 { 254 static G4LogicalVolumeStore worldStore; 255 if (fgInstance == nullptr) 256 { 257 fgInstance = &worldStore; 258 } 259 return fgInstance; 260 } 261