Geant4 Cross Reference |
1 // 1 2 // ******************************************* 3 // * License and Disclaimer 4 // * 5 // * The Geant4 software is copyright of th 6 // * the Geant4 Collaboration. It is provided 7 // * conditions of the Geant4 Software License 8 // * LICENSE and available at http://cern.ch/ 9 // * include a list of copyright holders. 10 // * 11 // * Neither the authors of this software syst 12 // * institutes,nor the agencies providing fin 13 // * work make any representation or warran 14 // * regarding this software system or assum 15 // * use. Please see the license in the file 16 // * for the full disclaimer and the limitatio 17 // * 18 // * This code implementation is the result 19 // * technical work of the GEANT4 collaboratio 20 // * By using, copying, modifying or distri 21 // * any work based on the software) you ag 22 // * use in resulting scientific publicati 23 // * acceptance of all terms of the Geant4 Sof 24 // ******************************************* 25 // 26 // G4MTcoutDestination class implementation 27 // 28 // Authors: M.Asai, A.Dotti (SLAC) - 23 May 20 29 // ------------------------------------------- 30 31 #include "G4MTcoutDestination.hh" 32 33 #include "G4AutoLock.hh" 34 #include "G4BuffercoutDestination.hh" 35 #include "G4FilecoutDestination.hh" 36 #include "G4LockcoutDestination.hh" 37 #include "G4MasterForwardcoutDestination.hh" 38 39 #include <cassert> 40 #include <sstream> 41 42 namespace 43 { 44 G4String empty = ""; 45 } 46 47 // ------------------------------------------- 48 G4MTcoutDestination::G4MTcoutDestination(const 49 : id(threadId) 50 { 51 // TODO: Move this out of here and in the ca 52 G4iosSetDestination(this); 53 54 stateMgr = G4StateManager::GetStateManager() 55 SetDefaultOutput(masterDestinationFlag, mast 56 } 57 58 // ------------------------------------------- 59 void G4MTcoutDestination::SetDefaultOutput(G4b 60 G4b 61 { 62 masterDestinationFlag = addmasterDestinat 63 masterDestinationFmtFlag = formatAlsoMaster; 64 // Formatter: add prefix to each thread 65 const auto f = [this](G4String& msg) -> G4bo 66 std::ostringstream str; 67 str << prefix; 68 if(id != G4Threading::GENERICTHREAD_ID) 69 { 70 str << id; 71 } 72 str << " > " << msg; 73 msg = str.str(); 74 return true; 75 }; 76 // Block cout if not in correct state 77 const auto filter_out = [this](G4String&) -> 78 return !( 79 this->ignoreCout || 80 (this->ignoreInit && this->stateMgr->Get 81 }; 82 83 // Default behavior, add a destination that 84 auto output = G4coutDestinationUPtr(new G 85 ref_defaultOut = output.get(); 86 output->AddDebugTransformer(filter_out); 87 output->AddDebugTransformer(f); 88 output->AddCoutTransformer(filter_out); 89 output->AddCoutTransformer(f); 90 output->AddCerrTransformer(f); 91 push_back(std::move(output)); 92 if(addmasterDestination) 93 { 94 AddMasterOutput(formatAlsoMaster); 95 } 96 } 97 98 // ------------------------------------------- 99 void G4MTcoutDestination::AddMasterOutput(G4bo 100 { 101 // Add a destination, that forwards the mess 102 auto forwarder = G4coutDestinationUPtr(new G 103 ref_masterOut = forwarder.get(); 104 const auto filter_out = [this](G4String&) -> 105 return !( 106 this->ignoreCout || 107 (this->ignoreInit && this->stateMgr->Get 108 }; 109 forwarder->AddDebugTransformer(filter_out); 110 forwarder->AddCoutTransformer(filter_out); 111 if(formatAlsoMaster) 112 { 113 // Formatter: add prefix to each thread 114 const auto f = [this](G4String& msg) -> G4 115 std::ostringstream str; 116 str << prefix; 117 if(id != G4Threading::GENERICTHREAD_ID) 118 { 119 str << id; 120 } 121 str << " > " << msg; 122 msg = str.str(); 123 return true; 124 }; 125 forwarder->AddDebugTransformer(f); 126 forwarder->AddCoutTransformer(f); 127 forwarder->AddCerrTransformer(f); 128 } 129 push_back(std::move(forwarder)); 130 } 131 132 // ------------------------------------------- 133 G4MTcoutDestination::~G4MTcoutDestination() 134 { 135 if(useBuffer) 136 { 137 DumpBuffer(); 138 } 139 } 140 141 // ------------------------------------------- 142 void G4MTcoutDestination::Reset() 143 { 144 clear(); 145 SetDefaultOutput(masterDestinationFlag, mast 146 } 147 148 // ------------------------------------------- 149 void G4MTcoutDestination::HandleFileCout(const 150 G4boo 151 { 152 // Logic: we create a file destination. We w 153 // stream and should discard everything in G 154 // First we create the destination with the 155 156 std::ios_base::openmode mode = 157 (ifAppend ? std::ios_base::app : std::ios_ 158 auto output = G4coutDestinationUPtr(new G4Fi 159 160 // This reacts only to G4cout, so let's make 161 output->AddDebugTransformer([](G4String&) { 162 output->AddCerrTransformer([](G4String&) { r 163 push_back(std::move(output)); 164 // Silence G4cout from default formatter 165 if(suppressDefault) 166 { 167 ref_defaultOut->AddCoutTransformer([](G4St 168 if(ref_masterOut != nullptr) 169 { 170 ref_masterOut->AddCoutTransformer([](G4S 171 } 172 } 173 } 174 175 // ------------------------------------------- 176 void G4MTcoutDestination::HandleFileCerr(const 177 G4boo 178 { 179 // See HandleFileCout for explanation, switc 180 181 std::ios_base::openmode mode = 182 (ifAppend ? std::ios_base::app : std::ios_ 183 auto output = G4coutDestinationUPtr(new G4Fi 184 output->AddDebugTransformer([](G4String&) { 185 output->AddCoutTransformer([](G4String&) { r 186 push_back(std::move(output)); 187 if(suppressDefault) 188 { 189 ref_defaultOut->AddCerrTransformer([](G4St 190 if(ref_masterOut != nullptr) 191 { 192 ref_masterOut->AddCerrTransformer([](G4S 193 } 194 } 195 } 196 197 // ------------------------------------------- 198 void G4MTcoutDestination::SetCoutFileName(cons 199 G4bo 200 { 201 // First let's go back to the default 202 Reset(); 203 if(fileN != "**Screen**") 204 { 205 HandleFileCout(fileN, ifAppend, true); 206 } 207 } 208 209 // ------------------------------------------- 210 void G4MTcoutDestination::EnableBuffering(G4bo 211 { 212 // I was using buffered output and now I wan 213 // buffer content and reset output 214 if(useBuffer && !flag) 215 { 216 DumpBuffer(); 217 Reset(); 218 } 219 else if(useBuffer && flag) 220 { /* do nothing: already using */ 221 } 222 else if(!useBuffer && !flag) 223 { /* do nothing: not using */ 224 } 225 else if(!useBuffer && flag) 226 { 227 // Remove everything, in this case also re 228 // thread, we want everything to be dumple 229 clear(); 230 const size_t infiniteSize = 0; 231 push_back(G4coutDestinationUPtr(new G4Buff 232 } 233 else // Should never happen 234 { 235 assert(false); 236 } 237 useBuffer = flag; 238 } 239 240 // ------------------------------------------- 241 void G4MTcoutDestination::AddCoutFileName(cons 242 G4bo 243 { 244 // This is like the equivalent SetCoutFileNa 245 // remove or silence what is already exisiti 246 HandleFileCout(fileN, ifAppend, false); 247 } 248 249 // ------------------------------------------- 250 void G4MTcoutDestination::SetCerrFileName(cons 251 G4bo 252 { 253 // See SetCoutFileName for explanation 254 Reset(); 255 if(fileN != "**Screen**") 256 { 257 HandleFileCerr(fileN, ifAppend, true); 258 } 259 } 260 261 // ------------------------------------------- 262 void G4MTcoutDestination::AddCerrFileName(cons 263 G4bo 264 { 265 HandleFileCerr(fileN, ifAppend, false); 266 } 267 268 // ------------------------------------------- 269 void G4MTcoutDestination::SetIgnoreCout(G4int 270 { 271 if(tid < 0) 272 { 273 ignoreCout = false; 274 } 275 else 276 { 277 ignoreCout = (tid != id); 278 } 279 } 280 281 namespace 282 { 283 G4Mutex coutm = G4MUTEX_INITIALIZER; 284 } 285 286 // ------------------------------------------- 287 void G4MTcoutDestination::DumpBuffer() 288 { 289 G4AutoLock l(&coutm); 290 std::ostringstream msg; 291 G4bool sep = false; 292 293 sep = false; 294 msg.str(""); 295 msg.clear(); 296 msg << "=======================\n"; 297 msg << "debug buffer(s) for worker with ID:" 298 G4coutDestination::ReceiveG4cout(msg.str()); 299 std::for_each(begin(), end(), [this, &sep](G 300 auto cout = dynamic_cast<G4BuffercoutDesti 301 if(cout != nullptr) 302 { 303 cout->FlushG4debug(); 304 if(sep) 305 { 306 G4coutDestination::ReceiveG4cout("==== 307 } 308 else 309 { 310 sep = true; 311 } 312 } 313 }); 314 315 sep = false; 316 msg.str(""); 317 msg.clear(); 318 msg << "=======================\n"; 319 msg << "cout buffer(s) for worker with ID:" 320 G4coutDestination::ReceiveG4cout(msg.str()); 321 std::for_each(begin(), end(), [this, &sep](G 322 auto cout = dynamic_cast<G4BuffercoutDesti 323 if(cout != nullptr) 324 { 325 cout->FlushG4cout(); 326 if(sep) 327 { 328 G4coutDestination::ReceiveG4cout("==== 329 } 330 else 331 { 332 sep = true; 333 } 334 } 335 }); 336 337 sep = false; 338 msg.str(""); 339 msg.clear(); 340 msg << "=======================\n"; 341 msg << "cerr buffer(s) for worker with ID:" 342 << std::endl; 343 G4coutDestination::ReceiveG4cout(msg.str()); 344 std::for_each(begin(), end(), [this, &sep](G 345 auto cout = dynamic_cast<G4BuffercoutDesti 346 if(cout != nullptr) 347 { 348 cout->FlushG4cerr(); 349 if(sep) 350 { 351 G4coutDestination::ReceiveG4cout("==== 352 } 353 else 354 { 355 sep = true; 356 } 357 } 358 }); 359 360 G4coutDestination::ReceiveG4cout("========== 361 } 362