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