Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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#include "G4strstreambuf.hh"
39
40#include <cassert>
41#include <sstream>
42
43namespace
44{
45 G4String empty = "";
46}
47
48// --------------------------------------------------------------------
50 : id(threadId)
51{
52 // TODO: Move these two out of here and in the caller
55
57 SetDefaultOutput(masterDestinationFlag, masterDestinationFmtFlag);
58}
59
60// --------------------------------------------------------------------
62 G4bool formatAlsoMaster)
63{
64 masterDestinationFlag = addmasterDestination;
65 masterDestinationFmtFlag = formatAlsoMaster;
66 // Formatter: add prefix to each thread
67 const auto f = [this](G4String& msg) -> G4bool {
68 std::ostringstream str;
69 str << prefix;
71 {
72 str << id;
73 }
74 str << " > " << msg;
75 msg = str.str();
76 return true;
77 };
78 // Block cout if not in correct state
79 const auto filter_out = [this](G4String&) -> G4bool {
80 return !(
81 this->ignoreCout ||
82 (this->ignoreInit && this->stateMgr->GetCurrentState() == G4State_Init));
83 };
84
85 // Default behavior, add a destination that uses cout and uses a mutex
87 ref_defaultOut = output.get();
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->AddCoutTransformer(filter_out);
110 if(formatAlsoMaster)
111 {
112 // Formatter: add prefix to each thread
113 const auto f = [this](G4String& msg) -> G4bool {
114 std::ostringstream str;
115 str << prefix;
117 {
118 str << id;
119 }
120 str << " > " << msg;
121 msg = str.str();
122 return true;
123 };
124 forwarder->AddCoutTransformer(f);
125 forwarder->AddCerrTransformer(f);
126 }
127 push_back(std::move(forwarder));
128}
129
130// --------------------------------------------------------------------
132{
133 if(useBuffer)
134 {
135 DumpBuffer();
136 }
137}
138
139// --------------------------------------------------------------------
141{
142 clear();
143 SetDefaultOutput(masterDestinationFlag, masterDestinationFmtFlag);
144}
145
146// --------------------------------------------------------------------
148 G4bool suppressDefault)
149{
150 // Logic: we create a file destination. We want this to get only the G4cout
151 // stream and should discard everything in G4cerr.
152 // First we create the destination with the appropriate open mode
153
154 std::ios_base::openmode mode =
155 (ifAppend ? std::ios_base::app : std::ios_base::trunc);
156 auto output = G4coutDestinationUPtr(new G4FilecoutDestination(fileN, mode));
157
158 // This reacts only to G4cout, so let's make a filter that removes everything
159 // from G4cerr
160 output->AddCerrTransformer([](G4String&) { return false; });
161 push_back(std::move(output));
162 // Silence G4cout from default formatter
163 if(suppressDefault)
164 {
165 ref_defaultOut->AddCoutTransformer([](G4String&) { return false; });
166 if(ref_masterOut != nullptr)
167 {
168 ref_masterOut->AddCoutTransformer([](G4String&) { return false; });
169 }
170 }
171}
172
173// --------------------------------------------------------------------
175 G4bool suppressDefault)
176{
177 // See HandleFileCout for explanation, switching cout with cerr
178
179 std::ios_base::openmode mode =
180 (ifAppend ? std::ios_base::app : std::ios_base::trunc);
181 auto output = G4coutDestinationUPtr(new G4FilecoutDestination(fileN, mode));
182 output->AddCoutTransformer([](G4String&) { return false; });
183 push_back(std::move(output));
184 if(suppressDefault)
185 {
186 ref_defaultOut->AddCerrTransformer([](G4String&) { return false; });
187 if(ref_masterOut != nullptr)
188 {
189 ref_masterOut->AddCerrTransformer([](G4String&) { return false; });
190 }
191 }
192}
193
194// --------------------------------------------------------------------
196 G4bool ifAppend)
197{
198 // First let's go back to the default
199 Reset();
200 if(fileN != "**Screen**")
201 {
202 HandleFileCout(fileN, ifAppend, true);
203 }
204}
205
206// --------------------------------------------------------------------
208{
209 // I was using buffered output and now I want to turn it off, dump current
210 // buffer content and reset output
211 if(useBuffer && !flag)
212 {
213 DumpBuffer();
214 Reset();
215 }
216 else if(useBuffer && flag)
217 { /* do nothing: already using */
218 }
219 else if(!useBuffer && !flag)
220 { /* do nothing: not using */
221 }
222 else if(!useBuffer && flag)
223 {
224 // Remove everything, in this case also removing the forward to the master
225 // thread, we want everything to be dumpled to a file
226 clear();
227 const size_t infiniteSize = 0;
228 push_back(G4coutDestinationUPtr(new G4BuffercoutDestination(infiniteSize)));
229 }
230 else // Should never happen
231 {
232 assert(false);
233 }
234 useBuffer = flag;
235}
236
237// --------------------------------------------------------------------
239 G4bool ifAppend)
240{
241 // This is like the equivalent SetCoutFileName, but in this case we do not
242 // remove or silence what is already exisiting
243 HandleFileCout(fileN, ifAppend, false);
244}
245
246// --------------------------------------------------------------------
248 G4bool ifAppend)
249{
250 // See SetCoutFileName for explanation
251 Reset();
252 if(fileN != "**Screen**")
253 {
254 HandleFileCerr(fileN, ifAppend, true);
255 }
256}
257
258// --------------------------------------------------------------------
260 G4bool ifAppend)
261{
262 HandleFileCerr(fileN, ifAppend, false);
263}
264
265// --------------------------------------------------------------------
267{
268 if(tid < 0)
269 {
270 ignoreCout = false;
271 }
272 else
273 {
274 ignoreCout = (tid != id);
275 }
276}
277
278namespace
279{
281}
282
283// --------------------------------------------------------------------
284void G4MTcoutDestination::DumpBuffer()
285{
286 G4AutoLock l(&coutm);
287 std::ostringstream msg;
288 msg << "=======================\n";
289 msg << "cout buffer(s) for worker with ID:" << id << std::endl;
291 G4bool sep = false;
292 std::for_each(begin(), end(), [this, &sep](G4coutDestinationUPtr& el) {
293 auto cout = dynamic_cast<G4BuffercoutDestination*>(el.get());
294 if(cout != nullptr)
295 {
296 cout->FlushG4cout();
297 if(sep)
298 {
299 G4coutDestination::ReceiveG4cout("==========\n");
300 }
301 else
302 {
303 sep = true;
304 }
305 }
306 });
307 sep = false;
308 msg.str("");
309 msg.clear();
310 msg << "=======================\n";
311 msg << "cerr buffer(s) for worker with ID:" << id << " (goes to std error)"
312 << std::endl;
314 std::for_each(begin(), end(), [this, &sep](G4coutDestinationUPtr& el) {
315 auto cout = dynamic_cast<G4BuffercoutDestination*>(el.get());
316 if(cout != nullptr)
317 {
318 cout->FlushG4cerr();
319 if(sep)
320 {
321 G4coutDestination::ReceiveG4cout("==========\n");
322 }
323 else
324 {
325 sep = true;
326 }
327 }
328 });
329 G4coutDestination::ReceiveG4cout("=======================\n");
330}
@ G4State_Init
@ G4State_Idle
std::unique_ptr< G4coutDestination > G4coutDestinationUPtr
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:85
std::mutex G4Mutex
Definition: G4Threading.hh:81
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL G4strstreambuf G4coutbuf
Definition: G4ios.cc:114
G4GLOB_DLL G4strstreambuf G4cerrbuf
Definition: G4ios.cc:115
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)
virtual G4int ReceiveG4cout(const G4String &msg)
void AddCoutTransformer(const Transformer &t)
void SetDestination(G4coutDestination *dest)