Geant4  v4-10.4-release
 모두 클래스 네임스페이스들 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 Friends 매크로 그룹들 페이지들
G4MTcoutDestination.cc
이 파일의 문서화 페이지로 가기
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 // $Id: G4MTcoutDestination.cc 66241 2012-12-13 18:34:42Z gunter $
27 //
28 // --------------------------------------------------------------------
29 //
30 // G4MTcoutDestination.cc
31 //
32 // --------------------------------------------------------------------
33 
34 #include <sstream>
35 #include <assert.h>
36 
37 #include "G4MTcoutDestination.hh"
38 #include "G4LockcoutDestination.hh"
40 #include "G4FilecoutDestination.hh"
42 #include "G4strstreambuf.hh"
43 #include "G4AutoLock.hh"
44 
45 namespace
46 {
47  G4String empty = "";
48 }
49 
51  : ref_defaultOut(nullptr), ref_masterOut(nullptr),
52  masterDestinationFlag(true),masterDestinationFmtFlag(true),
53  id(threadId), useBuffer(false), ignoreCout(false), ignoreInit(true),
54  prefix("G4WT")
55 {
56  // TODO: Move these two out of here and in the caller
59 
62 }
63 
64 void G4MTcoutDestination::SetDefaultOutput( G4bool addmasterDestination ,
65  G4bool formatAlsoMaster )
66 {
67  masterDestinationFlag = addmasterDestination;
68  masterDestinationFmtFlag = formatAlsoMaster;
69  // Formatter: add prefix to each thread
70  const auto f = [this](G4String& msg)->G4bool {
71  std::ostringstream str;
72  str<<prefix;
73  if ( id!=G4Threading::GENERICTHREAD_ID ) str<<id;
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  if (this->ignoreCout ||
81  ( this->ignoreInit &&
82  this->stateMgr->GetCurrentState() == G4State_Init ) )
83  { return false; }
84  return true;
85  };
86 
87  // Default behavior, add a destination that uses cout and uses a mutex
88  auto output = G4coutDestinationUPtr( new G4LockcoutDestination );
89  ref_defaultOut = output.get();
90  output->AddCoutTransformer(filter_out);
91  output->AddCoutTransformer(f);
92  output->AddCerrTransformer(f);
93  push_back( std::move(output) );
94  if ( addmasterDestination )
95  {
96  AddMasterOutput(formatAlsoMaster);
97  }
98 }
99 
101 {
102  // Add a destination, that forwards the message to the master thread
104  ref_masterOut = forwarder.get();
105  const auto filter_out = [this](G4String&)->G4bool {
106  if (this->ignoreCout ||
107  ( this->ignoreInit &&
108  this->stateMgr->GetCurrentState() == G4State_Idle ) )
109  { return false; }
110  return true;
111  };
112  forwarder->AddCoutTransformer(filter_out);
113  if ( formatAlsoMaster )
114  {
115  // Formatter: add prefix to each thread
116  const auto f = [this](G4String& msg)->G4bool {
117  std::ostringstream str;
118  str<<prefix;
119  if ( id!=G4Threading::GENERICTHREAD_ID ) str<<id;
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 ) DumpBuffer();
134 }
135 
137 {
138  clear();
140 }
141 
143  G4bool suppressDefault)
144 {
145  // Logic: we create a file destination. We want this to get only the G4cout
146  // stream and should discard everything in G4cerr.
147  // First we create the destination with the appropriate open mode
148 
149  std::ios_base::openmode mode = (ifAppend ? std::ios_base::app
150  : std::ios_base::trunc);
151  auto output = G4coutDestinationUPtr( new G4FilecoutDestination(fileN,mode));
152 
153  // This reacts only to G4cout, so let's make a filter that removes everything
154  // from G4cerr
155  output->AddCerrTransformer( [](G4String&) { return false;} );
156  push_back(std::move(output));
157  // Silence G4cout from default formatter
158  if ( suppressDefault )
159  {
160  ref_defaultOut->AddCoutTransformer( [](G4String&) { return false; } );
161  if ( ref_masterOut )
162  ref_masterOut->AddCoutTransformer( [](G4String&) { return false; } );
163  }
164 }
165 
167  G4bool suppressDefault)
168 {
169  // See HandleFileCout for explanation, switching cout with cerr
170 
171  std::ios_base::openmode mode = (ifAppend ? std::ios_base::app
172  : std::ios_base::trunc);
173  auto output = G4coutDestinationUPtr( new G4FilecoutDestination(fileN,mode));
174  output->AddCoutTransformer( [](G4String&) { return false;} );
175  push_back(std::move(output));
176  if ( suppressDefault )
177  {
178  ref_defaultOut->AddCerrTransformer( [](G4String&) { return false; } );
179  if ( ref_masterOut )
180  ref_masterOut->AddCerrTransformer( [](G4String&) { return false; } );
181  }
182 }
183 
185  G4bool ifAppend)
186 {
187  // First let's go back to the default
188  Reset();
189  if ( fileN != "**Screen**" )
190  {
191  HandleFileCout(fileN,ifAppend,true);
192  }
193 }
194 
196 {
197  // I was using buffered output and now I want to turn it off, dump current
198  // buffer content and reset output
199  if ( useBuffer && !flag )
200  {
201  DumpBuffer();
202  Reset();
203  }
204  else if ( useBuffer && flag ) { /* do nothing: already using */ }
205  else if ( !useBuffer && !flag ) { /* do nothing: not using */ }
206  else if ( !useBuffer && flag )
207  {
208  // Remove everything, in this case also removing the forward to the master
209  // thread, we want everything to be dumpled to a file
210  clear();
211  const size_t infiniteSize = 0;
212  push_back(G4coutDestinationUPtr(new G4BuffercoutDestination(infiniteSize)));
213  }
214  else { assert(false); } // Should never happen
215  useBuffer = flag;
216 }
217 
219  G4bool ifAppend)
220 {
221  // This is like the equivalent SetCoutFileName, but in this case we do not
222  // remove or silence what is already exisiting
223  HandleFileCout(fileN,ifAppend,false);
224 }
225 
227  G4bool ifAppend)
228 {
229  // See SetCoutFileName for explanation
230  Reset();
231  if ( fileN != "**Screen**")
232  {
233  HandleFileCerr(fileN,ifAppend,true);
234  }
235 }
236 
238  G4bool ifAppend)
239 {
240  HandleFileCerr(fileN,ifAppend,false);
241 }
242 
244 {
245  if (tid<0) { ignoreCout = false; }
246  else { ignoreCout = (tid!=id); }
247 }
248 
249 namespace
250 {
252 }
253 
255 {
256  G4AutoLock l(&coutm);
257  std::ostringstream msg;
258  msg << "=======================\n";
259  msg << "cout buffer(s) for worker with ID:" << id << std::endl;
261  G4bool sep = false;
262  std::for_each( begin() , end(),
263  [this,&sep](G4coutDestinationUPtr& el) {
264  auto cout = dynamic_cast<G4BuffercoutDestination*>(el.get());
265  if ( cout != nullptr ) {
266  cout->FlushG4cout();
267  if ( sep ) { G4coutDestination::ReceiveG4cout("==========\n"); }
268  else { sep = true; }
269  }
270  } );
271  sep = false;
272  msg.str("");
273  msg.clear();
274  msg << "=======================\n";
275  msg << "cerr buffer(s) for worker with ID:" << id
276  << " (goes to std error)" << std::endl;
278  std::for_each( begin() , end(),
279  [this,&sep](G4coutDestinationUPtr& el) {
280  auto cout = dynamic_cast<G4BuffercoutDestination*>(el.get());
281  if ( cout != nullptr ) {
282  cout->FlushG4cerr();
283  if (sep ) { G4coutDestination::ReceiveG4cout("==========\n"); }
284  else { sep = true; }
285  }
286  } );
287  G4coutDestination::ReceiveG4cout("=======================\n");
288 }
void AddMasterOutput(G4bool formatAlsoMaster)
void AddCoutFileName(const G4String &fileN="G4cout.txt", G4bool ifAppend=true)
std::unique_ptr< G4coutDestination > G4coutDestinationUPtr
G4StateManager * stateMgr
void SetDefaultOutput(G4bool addMasterDestination=true, G4bool formatAlsoMaster=true)
void AddCerrFileName(const G4String &fileN="G4cerr.txt", G4bool ifAppend=true)
bool G4bool
Definition: G4Types.hh:79
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:88
void SetCerrFileName(const G4String &fileN="G4cerr.txt", G4bool ifAppend=true)
G4strstreambuf G4coutbuf
Definition: G4ios.cc:104
void EnableBuffering(G4bool flag=true)
void HandleFileCout(G4String fileN, G4bool appendFlag, G4bool suppressDefault)
void SetDestination(G4coutDestination *dest)
void AddCoutTransformer(const Transformer &t)
void SetIgnoreCout(G4int tid=0)
G4MTcoutDestination(const G4int &threadId)
void HandleFileCerr(G4String fileN, G4bool appendFlag, G4bool suppressDefault)
int G4int
Definition: G4Types.hh:78
G4ApplicationState GetCurrentState() const
void AddCerrTransformer(const Transformer &t)
G4coutDestination * ref_masterOut
virtual G4int ReceiveG4cout(const G4String &msg)
G4strstreambuf G4cerrbuf
Definition: G4ios.cc:105
void SetCoutFileName(const G4String &fileN="G4cout.txt", G4bool ifAppend=true)
G4coutDestination * ref_defaultOut
vec_iX clear()
static G4StateManager * GetStateManager()
std::mutex G4Mutex
Definition: G4Threading.hh:84