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 37 42 namespace << 38 G4MTcoutDestination::G4MTcoutDestination(const G4int& threadId, 43 { << 39 std::ostream& co, std::ostream& ce) 44 G4String empty = ""; << 40 : finalcout(co), finalcerr(ce), id(threadId), useBuffer(false), >> 41 threadCoutToFile(false), threadCerrToFile(false), >> 42 ignoreCout(false), ignoreInit(true) >> 43 { >> 44 G4coutbuf.SetDestination(this); >> 45 G4cerrbuf.SetDestination(this); >> 46 prefix = "G4WT"; 45 } 47 } 46 48 47 // ------------------------------------------- << 49 G4MTcoutDestination::~G4MTcoutDestination() 48 G4MTcoutDestination::G4MTcoutDestination(const << 49 : id(threadId) << 50 { 50 { 51 // TODO: Move this out of here and in the ca << 51 if( useBuffer ) DumpBuffer(); 52 G4iosSetDestination(this); << 52 if( threadCoutToFile ) CloseCoutFile(); 53 << 53 if( threadCerrToFile ) CloseCerrFile(); 54 stateMgr = G4StateManager::GetStateManager() << 55 SetDefaultOutput(masterDestinationFlag, mast << 56 } 54 } 57 55 58 // ------------------------------------------- << 56 namespace { G4Mutex coutm = G4MUTEX_INITIALIZER; } 59 void G4MTcoutDestination::SetDefaultOutput(G4b << 57 #include "G4StateManager.hh" 60 G4b << 58 >> 59 G4int G4MTcoutDestination::ReceiveG4cout(const G4String& msg) 61 { 60 { 62 masterDestinationFlag = addmasterDestinat << 61 if( threadCoutToFile ) 63 masterDestinationFmtFlag = formatAlsoMaster; << 62 { coutFile<<msg<<std::flush; } 64 // Formatter: add prefix to each thread << 63 else if( useBuffer ) 65 const auto f = [this](G4String& msg) -> G4bo << 64 { cout_buffer<<msg; } 66 std::ostringstream str; << 65 else if( !ignoreCout ) 67 str << prefix; << 66 { 68 if(id != G4Threading::GENERICTHREAD_ID) << 67 if(!ignoreInit || >> 68 G4StateManager::GetStateManager()->GetCurrentState() != G4State_Idle ) 69 { 69 { 70 str << id; << 70 G4AutoLock l(&coutm); >> 71 finalcout<<prefix; >> 72 if ( id!=G4Threading::GENERICTHREAD_ID ) finalcout<<id; >> 73 finalcout<<" > "<<msg<<std::flush; 71 } 74 } 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 } 75 } >> 76 //forward message to master G4coutDestination if set >> 77 if ( masterG4coutDestination && !ignoreCout && >> 78 ( !ignoreInit || G4StateManager::GetStateManager()->GetCurrentState() != G4State_Idle ) >> 79 ){ >> 80 G4AutoLock l(&coutm); >> 81 std::stringstream ss; >> 82 ss<<prefix; >> 83 if ( id!=G4Threading::GENERICTHREAD_ID ) ss<<id; >> 84 ss<<" > "<<msg; >> 85 masterG4coutDestination->ReceiveG4cout(ss.str()); >> 86 } >> 87 return 0; 96 } 88 } 97 89 98 // ------------------------------------------- << 90 G4int G4MTcoutDestination::ReceiveG4cerr(const G4String& msg) 99 void G4MTcoutDestination::AddMasterOutput(G4bo << 100 { 91 { 101 // Add a destination, that forwards the mess << 92 if( threadCerrToFile ) 102 auto forwarder = G4coutDestinationUPtr(new G << 93 { cerrFile<<msg<<std::flush; } 103 ref_masterOut = forwarder.get(); << 94 if( useBuffer ) 104 const auto filter_out = [this](G4String&) -> << 95 { cerr_buffer<<msg; } 105 return !( << 96 else 106 this->ignoreCout || << 97 { G4AutoLock l(&coutm); 107 (this->ignoreInit && this->stateMgr->Get << 98 finalcerr<<prefix; 108 }; << 99 if ( id!=G4Threading::GENERICTHREAD_ID ) finalcerr<<id; 109 forwarder->AddDebugTransformer(filter_out); << 100 finalcerr<<" > "<<msg<<std::flush; 110 forwarder->AddCoutTransformer(filter_out); << 101 } 111 if(formatAlsoMaster) << 102 //forward message to master G4coutDestination if set 112 { << 103 if ( masterG4coutDestination && !ignoreCout && 113 // Formatter: add prefix to each thread << 104 ( !ignoreInit || G4StateManager::GetStateManager()->GetCurrentState() != G4State_Idle ) 114 const auto f = [this](G4String& msg) -> G4 << 105 ){ 115 std::ostringstream str; << 106 G4AutoLock l(&coutm); 116 str << prefix; << 107 std::stringstream ss; 117 if(id != G4Threading::GENERICTHREAD_ID) << 108 ss<<prefix; 118 { << 109 if ( id!=G4Threading::GENERICTHREAD_ID ) ss<<id; 119 str << id; << 110 ss<<" > "<<msg; 120 } << 111 masterG4coutDestination->ReceiveG4cerr(ss.str()); 121 str << " > " << msg; << 112 } 122 msg = str.str(); << 113 return 0; 123 return true; << 124 }; << 125 forwarder->AddDebugTransformer(f); << 126 forwarder->AddCoutTransformer(f); << 127 forwarder->AddCerrTransformer(f); << 128 } << 129 push_back(std::move(forwarder)); << 130 } 114 } 131 115 132 // ------------------------------------------- << 116 void G4MTcoutDestination::SetCoutFileName(const G4String& fileN, G4bool ifAppend) 133 G4MTcoutDestination::~G4MTcoutDestination() << 134 { 117 { 135 if(useBuffer) << 118 if( threadCoutToFile ) CloseCoutFile(); >> 119 if( fileN == "**Screen**" ) return; >> 120 if( ! coutFile.is_open() ) 136 { 121 { 137 DumpBuffer(); << 122 std::ios::openmode mode = std::ios::out; >> 123 if ( ifAppend ) mode |= std::ios::app; >> 124 coutFile.open(fileN,mode); 138 } 125 } >> 126 threadCoutToFile = true; 139 } 127 } 140 128 141 // ------------------------------------------- << 129 void G4MTcoutDestination::SetCerrFileName(const G4String& fileN, G4bool ifAppend) 142 void G4MTcoutDestination::Reset() << 143 { 130 { 144 clear(); << 131 if( threadCerrToFile ) CloseCerrFile(); 145 SetDefaultOutput(masterDestinationFlag, mast << 132 if( fileN == "**Screen**" ) return; 146 } << 133 if( ! cerrFile.is_open() ) 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 { 134 { 205 HandleFileCout(fileN, ifAppend, true); << 135 std::ios::openmode mode = std::ios::out; >> 136 if ( ifAppend ) mode |= std::ios::app; >> 137 cerrFile.open(fileN,mode); 206 } 138 } >> 139 threadCerrToFile = true; 207 } 140 } 208 141 209 // ------------------------------------------- << 210 void G4MTcoutDestination::EnableBuffering(G4bo 142 void G4MTcoutDestination::EnableBuffering(G4bool flag) 211 { 143 { 212 // I was using buffered output and now I wan << 144 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; 145 useBuffer = flag; 238 } 146 } 239 147 240 // ------------------------------------------- << 148 void G4MTcoutDestination::SetPrefixString(const G4String& wd) 241 void G4MTcoutDestination::AddCoutFileName(cons << 149 { 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 150 261 // ------------------------------------------- << 151 void G4MTcoutDestination::SetIgnoreCout(G4int tid) 262 void G4MTcoutDestination::AddCerrFileName(cons << 263 G4bo << 264 { 152 { 265 HandleFileCerr(fileN, ifAppend, false); << 153 if(tid<0) >> 154 { ignoreCout = false; } >> 155 else >> 156 { ignoreCout = (tid!=id); } 266 } 157 } 267 158 268 // ------------------------------------------- << 159 void G4MTcoutDestination::CloseCoutFile() 269 void G4MTcoutDestination::SetIgnoreCout(G4int << 270 { 160 { 271 if(tid < 0) << 161 if( coutFile.is_open() ) coutFile.close(); 272 { << 162 threadCoutToFile = false; 273 ignoreCout = false; << 274 } << 275 else << 276 { << 277 ignoreCout = (tid != id); << 278 } << 279 } 163 } 280 164 281 namespace << 165 void G4MTcoutDestination::CloseCerrFile() 282 { 166 { 283 G4Mutex coutm = G4MUTEX_INITIALIZER; << 167 if( cerrFile.is_open() ) cerrFile.close(); >> 168 threadCerrToFile = false; 284 } 169 } 285 170 286 // ------------------------------------------- << 287 void G4MTcoutDestination::DumpBuffer() 171 void G4MTcoutDestination::DumpBuffer() 288 { 172 { 289 G4AutoLock l(&coutm); 173 G4AutoLock l(&coutm); 290 std::ostringstream msg; << 174 finalcout<<"====================="<<std::endl; 291 G4bool sep = false; << 175 finalcout<<"cout buffer for worker with ID:"<<id<<std::endl; 292 << 176 finalcout<<cout_buffer.str()<<std::endl; 293 sep = false; << 177 finalcerr<<"====================="<<std::endl; 294 msg.str(""); << 178 finalcerr<<"cerr buffer for worker with ID:"<<id<<std::endl; 295 msg.clear(); << 179 finalcerr<<cerr_buffer.str()<<std::endl; 296 msg << "=======================\n"; << 180 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 } 181 } >> 182 362 183