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 // G4MTcoutDestination class implementation << 27 // 26 // 28 // Authors: M.Asai, A.Dotti (SLAC) - 23 May 20 << 27 // $Id: G4MTcoutDestination.cc 66241 2012-12-13 18:34:42Z gunter $ 29 // ------------------------------------------- << 28 // >> 29 // >> 30 // ---------------------------------------------------------------------- >> 31 // G4MTcoutDestination >> 32 // 30 33 31 #include "G4MTcoutDestination.hh" 34 #include "G4MTcoutDestination.hh" 32 << 35 #include "G4strstreambuf.hh" 33 #include "G4AutoLock.hh" 36 #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 37 98 // ------------------------------------------- << 38 G4MTcoutDestination::G4MTcoutDestination(const G4int& threadId, 99 void G4MTcoutDestination::AddMasterOutput(G4bo << 39 std::ostream& co, std::ostream& ce) 100 { << 40 : finalcout(co), finalcerr(ce), id(threadId), useBuffer(false), 101 // Add a destination, that forwards the mess << 41 threadCoutToFile(false), threadCerrToFile(false), ignoreCout(false) 102 auto forwarder = G4coutDestinationUPtr(new G << 42 { 103 ref_masterOut = forwarder.get(); << 43 G4coutbuf.SetDestination(this); 104 const auto filter_out = [this](G4String&) -> << 44 G4cerrbuf.SetDestination(this); 105 return !( << 45 prefix = "G4WT"; 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 } 46 } 131 47 132 // ------------------------------------------- << 133 G4MTcoutDestination::~G4MTcoutDestination() 48 G4MTcoutDestination::~G4MTcoutDestination() 134 { 49 { 135 if(useBuffer) << 50 if( useBuffer ) DumpBuffer(); 136 { << 51 if( threadCoutToFile ) CloseCoutFile(); 137 DumpBuffer(); << 52 if( threadCerrToFile ) CloseCerrFile(); 138 } << 139 } 53 } 140 54 141 // ------------------------------------------- << 55 namespace { G4Mutex coutm = G4MUTEX_INITIALIZER; } 142 void G4MTcoutDestination::Reset() << 56 >> 57 G4int G4MTcoutDestination::ReceiveG4cout(const G4String& msg) 143 { 58 { 144 clear(); << 59 if( threadCoutToFile ) 145 SetDefaultOutput(masterDestinationFlag, mast << 60 { coutFile<<msg<<std::flush; } >> 61 else if( useBuffer ) >> 62 { cout_buffer<<msg; } >> 63 else if( !ignoreCout ) >> 64 { G4AutoLock l(&coutm); finalcout<<prefix<<id<<" > "<<msg; } >> 65 return 0; 146 } 66 } 147 67 148 // ------------------------------------------- << 68 G4int G4MTcoutDestination::ReceiveG4cerr(const G4String& msg) 149 void G4MTcoutDestination::HandleFileCout(const << 69 { 150 G4boo << 70 if( threadCerrToFile ) 151 { << 71 { cerrFile<<msg<<std::flush; } 152 // Logic: we create a file destination. We w << 72 if( useBuffer ) 153 // stream and should discard everything in G << 73 { cerr_buffer<<msg; } 154 // First we create the destination with the << 74 else 155 << 75 { G4AutoLock l(&coutm); finalcerr<<prefix<<id<<" > "<<msg; } 156 std::ios_base::openmode mode = << 76 return 0; 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 } 77 } 174 78 175 // ------------------------------------------- << 79 void G4MTcoutDestination::SetCoutFileName(const G4String& fileN, G4bool ifAppend) 176 void G4MTcoutDestination::HandleFileCerr(const << 80 { 177 G4boo << 81 if( threadCoutToFile ) CloseCoutFile(); 178 { << 82 if( fileN == "**Screen**" ) return; 179 // See HandleFileCout for explanation, switc << 83 if( ! coutFile.is_open() ) 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 { 84 { 189 ref_defaultOut->AddCerrTransformer([](G4St << 85 std::ios::openmode mode = std::ios::out; 190 if(ref_masterOut != nullptr) << 86 if ( ifAppend ) mode |= std::ios::app; 191 { << 87 coutFile.open(fileN,mode); 192 ref_masterOut->AddCerrTransformer([](G4S << 193 } << 194 } 88 } >> 89 threadCoutToFile = true; 195 } 90 } 196 91 197 // ------------------------------------------- << 92 void G4MTcoutDestination::SetCerrFileName(const G4String& fileN, G4bool ifAppend) 198 void G4MTcoutDestination::SetCoutFileName(cons << 93 { 199 G4bo << 94 if( threadCerrToFile ) CloseCerrFile(); 200 { << 95 if( fileN == "**Screen**" ) return; 201 // First let's go back to the default << 96 if( ! cerrFile.is_open() ) 202 Reset(); << 203 if(fileN != "**Screen**") << 204 { 97 { 205 HandleFileCout(fileN, ifAppend, true); << 98 std::ios::openmode mode = std::ios::out; >> 99 if ( ifAppend ) mode |= std::ios::app; >> 100 cerrFile.open(fileN,mode); 206 } 101 } >> 102 threadCerrToFile = true; 207 } 103 } 208 104 209 // ------------------------------------------- << 210 void G4MTcoutDestination::EnableBuffering(G4bo 105 void G4MTcoutDestination::EnableBuffering(G4bool flag) 211 { 106 { 212 // I was using buffered output and now I wan << 107 if(useBuffer && !flag) DumpBuffer(); 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; 108 useBuffer = flag; 238 } 109 } 239 110 240 // ------------------------------------------- << 111 void G4MTcoutDestination::SetPrefixString(const G4String& wd) 241 void G4MTcoutDestination::AddCoutFileName(cons << 112 { prefix = wd; } 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 113 261 // ------------------------------------------- << 114 void G4MTcoutDestination::SetIgnoreCout(G4int tid) 262 void G4MTcoutDestination::AddCerrFileName(cons << 263 G4bo << 264 { 115 { 265 HandleFileCerr(fileN, ifAppend, false); << 116 if(tid<0) >> 117 { ignoreCout = false; } >> 118 else >> 119 { ignoreCout = (tid!=id); } 266 } 120 } 267 121 268 // ------------------------------------------- << 122 void G4MTcoutDestination::CloseCoutFile() 269 void G4MTcoutDestination::SetIgnoreCout(G4int << 270 { 123 { 271 if(tid < 0) << 124 if( coutFile.is_open() ) coutFile.close(); 272 { << 125 threadCoutToFile = false; 273 ignoreCout = false; << 274 } << 275 else << 276 { << 277 ignoreCout = (tid != id); << 278 } << 279 } 126 } 280 127 281 namespace << 128 void G4MTcoutDestination::CloseCerrFile() 282 { 129 { 283 G4Mutex coutm = G4MUTEX_INITIALIZER; << 130 if( cerrFile.is_open() ) cerrFile.close(); >> 131 threadCerrToFile = false; 284 } 132 } 285 133 286 // ------------------------------------------- << 287 void G4MTcoutDestination::DumpBuffer() 134 void G4MTcoutDestination::DumpBuffer() 288 { 135 { 289 G4AutoLock l(&coutm); 136 G4AutoLock l(&coutm); 290 std::ostringstream msg; << 137 finalcout<<"====================="<<std::endl; 291 G4bool sep = false; << 138 finalcout<<"cout buffer for worker with ID:"<<id<<std::endl; 292 << 139 finalcout<<cout_buffer.str()<<std::endl; 293 sep = false; << 140 finalcerr<<"====================="<<std::endl; 294 msg.str(""); << 141 finalcerr<<"cerr buffer for worker with ID:"<<id<<std::endl; 295 msg.clear(); << 142 finalcerr<<cerr_buffer.str()<<std::endl; 296 msg << "=======================\n"; << 143 finalcerr<<"====================="<<std::endl; 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 } 144 } >> 145 362 146