Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4MTcoutDestination.cc
Go to the documentation of this file.
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// G4MTcoutDestination class implementation
27//
28// Authors: M.Asai, A.Dotti (SLAC) - 23 May 2013
29// ---------------------------------------------------------------
30
32
33#include "G4AutoLock.hh"
38
39#include <cassert>
40#include <sstream>
41
42namespace
43{
44 G4String empty = "";
45}
46
47// --------------------------------------------------------------------
49 : id(threadId)
50{
51 // TODO: Move this out of here and in the caller
53
55 SetDefaultOutput(masterDestinationFlag, masterDestinationFmtFlag);
56}
57
58// --------------------------------------------------------------------
60 G4bool formatAlsoMaster)
61{
62 masterDestinationFlag = addmasterDestination;
63 masterDestinationFmtFlag = formatAlsoMaster;
64 // Formatter: add prefix to each thread
65 const auto f = [this](G4String& msg) -> G4bool {
66 std::ostringstream str;
67 str << prefix;
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&) -> G4bool {
78 return !(
79 this->ignoreCout ||
80 (this->ignoreInit && this->stateMgr->GetCurrentState() == G4State_Init));
81 };
82
83 // Default behavior, add a destination that uses cout and uses a mutex
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// --------------------------------------------------------------------
100{
101 // Add a destination, that forwards the message to the master thread
103 ref_masterOut = forwarder.get();
104 const auto filter_out = [this](G4String&) -> G4bool {
105 return !(
106 this->ignoreCout ||
107 (this->ignoreInit && this->stateMgr->GetCurrentState() == G4State_Idle));
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) -> G4bool {
115 std::ostringstream str;
116 str << prefix;
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// --------------------------------------------------------------------
134{
135 if(useBuffer)
136 {
137 DumpBuffer();
138 }
139}
140
141// --------------------------------------------------------------------
143{
144 clear();
145 SetDefaultOutput(masterDestinationFlag, masterDestinationFmtFlag);
146}
147
148// --------------------------------------------------------------------
150 G4bool suppressDefault)
151{
152 // Logic: we create a file destination. We want this to get only the G4cout
153 // stream and should discard everything in G4cerr.
154 // First we create the destination with the appropriate open mode
155
156 std::ios_base::openmode mode =
157 (ifAppend ? std::ios_base::app : std::ios_base::trunc);
158 auto output = G4coutDestinationUPtr(new G4FilecoutDestination(fileN, mode));
159
160 // This reacts only to G4cout, so let's make a filter that ignores all other streams
161 output->AddDebugTransformer([](G4String&) { return false; });
162 output->AddCerrTransformer([](G4String&) { return false; });
163 push_back(std::move(output));
164 // Silence G4cout from default formatter
165 if(suppressDefault)
166 {
167 ref_defaultOut->AddCoutTransformer([](G4String&) { return false; });
168 if(ref_masterOut != nullptr)
169 {
170 ref_masterOut->AddCoutTransformer([](G4String&) { return false; });
171 }
172 }
173}
174
175// --------------------------------------------------------------------
177 G4bool suppressDefault)
178{
179 // See HandleFileCout for explanation, switching cout with cerr
180
181 std::ios_base::openmode mode =
182 (ifAppend ? std::ios_base::app : std::ios_base::trunc);
183 auto output = G4coutDestinationUPtr(new G4FilecoutDestination(fileN, mode));
184 output->AddDebugTransformer([](G4String&) { return false; });
185 output->AddCoutTransformer([](G4String&) { return false; });
186 push_back(std::move(output));
187 if(suppressDefault)
188 {
189 ref_defaultOut->AddCerrTransformer([](G4String&) { return false; });
190 if(ref_masterOut != nullptr)
191 {
192 ref_masterOut->AddCerrTransformer([](G4String&) { return false; });
193 }
194 }
195}
196
197// --------------------------------------------------------------------
199 G4bool ifAppend)
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// --------------------------------------------------------------------
211{
212 // I was using buffered output and now I want to turn it off, dump current
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 removing the forward to the master
228 // thread, we want everything to be dumpled to a file
229 clear();
230 const size_t infiniteSize = 0;
231 push_back(G4coutDestinationUPtr(new G4BuffercoutDestination(infiniteSize)));
232 }
233 else // Should never happen
234 {
235 assert(false);
236 }
237 useBuffer = flag;
238}
239
240// --------------------------------------------------------------------
242 G4bool ifAppend)
243{
244 // This is like the equivalent SetCoutFileName, but in this case we do not
245 // remove or silence what is already exisiting
246 HandleFileCout(fileN, ifAppend, false);
247}
248
249// --------------------------------------------------------------------
251 G4bool ifAppend)
252{
253 // See SetCoutFileName for explanation
254 Reset();
255 if(fileN != "**Screen**")
256 {
257 HandleFileCerr(fileN, ifAppend, true);
258 }
259}
260
261// --------------------------------------------------------------------
263 G4bool ifAppend)
264{
265 HandleFileCerr(fileN, ifAppend, false);
266}
267
268// --------------------------------------------------------------------
270{
271 if(tid < 0)
272 {
273 ignoreCout = false;
274 }
275 else
276 {
277 ignoreCout = (tid != id);
278 }
279}
280
281namespace
282{
284}
285
286// --------------------------------------------------------------------
287void 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:" << id << std::endl;
299 std::for_each(begin(), end(), [this, &sep](G4coutDestinationUPtr& el) {
300 auto cout = dynamic_cast<G4BuffercoutDestination*>(el.get());
301 if(cout != nullptr)
302 {
303 cout->FlushG4debug();
304 if(sep)
305 {
306 G4coutDestination::ReceiveG4cout("==========\n");
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:" << id << std::endl;
321 std::for_each(begin(), end(), [this, &sep](G4coutDestinationUPtr& el) {
322 auto cout = dynamic_cast<G4BuffercoutDestination*>(el.get());
323 if(cout != nullptr)
324 {
325 cout->FlushG4cout();
326 if(sep)
327 {
328 G4coutDestination::ReceiveG4cout("==========\n");
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:" << id << " (goes to std error)"
342 << std::endl;
344 std::for_each(begin(), end(), [this, &sep](G4coutDestinationUPtr& el) {
345 auto cout = dynamic_cast<G4BuffercoutDestination*>(el.get());
346 if(cout != nullptr)
347 {
348 cout->FlushG4cerr();
349 if(sep)
350 {
351 G4coutDestination::ReceiveG4cout("==========\n");
352 }
353 else
354 {
355 sep = true;
356 }
357 }
358 });
359
360 G4coutDestination::ReceiveG4cout("=======================\n");
361}
@ G4State_Init
@ G4State_Idle
std::unique_ptr< G4coutDestination > G4coutDestinationUPtr
#define G4MUTEX_INITIALIZER
std::mutex G4Mutex
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
void G4iosSetDestination(G4coutDestination *sink)
Definition G4ios.cc:270
void AddCerrFileName(const G4String &fileN="G4cerr.txt", G4bool ifAppend=true)
void SetDefaultOutput(G4bool addMasterDestination=true, G4bool formatAlsoMaster=true)
void EnableBuffering(G4bool flag=true)
void SetCoutFileName(const G4String &fileN="G4cout.txt", G4bool ifAppend=true)
G4MTcoutDestination(const G4int &threadId)
void AddCoutFileName(const G4String &fileN="G4cout.txt", G4bool ifAppend=true)
void HandleFileCout(const G4String &fileN, G4bool appendFlag, G4bool suppressDefault)
void HandleFileCerr(const G4String &fileN, G4bool appendFlag, G4bool suppressDefault)
void SetIgnoreCout(G4int tid=0)
void SetCerrFileName(const G4String &fileN="G4cerr.txt", G4bool ifAppend=true)
void AddMasterOutput(G4bool formatAlsoMaster)
const G4ApplicationState & GetCurrentState() const
static G4StateManager * GetStateManager()
void AddCerrTransformer(const Transformer &t)
void AddDebugTransformer(const Transformer &t)
virtual G4int ReceiveG4cout(const G4String &msg)
void AddCoutTransformer(const Transformer &t)