Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4ios.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// G4ios implementation
27//
28// Authors: H.Yoshida, M.Nagamatu - November 1998
29// --------------------------------------------------------------------
30
31#include "G4ios.hh"
32
33#include "G4coutDestination.hh"
34
35#include <iostream>
36
37namespace
38{
39// Concrete streambuf redirecting output to G4coutDestination via G4cout etc
40// Templated on two policy types to determine:
41// - DestinationPolicy: which member member function of G4coutDestination to redirect to
42// - DefaultPolicy: what to do if G4coutDestination is default (nullptr)
43template <typename DestinationPolicy, typename DefaultPolicy>
44class G4strstreambuf : public std::basic_streambuf<char>
45{
46 public:
47 G4strstreambuf()
48 {
49 size = 4095;
50 buffer = new char[size + 1];
51 }
52
53 ~G4strstreambuf() override
54 {
55 // flushing buffer...
56 // std::cout is used because destination object may not be alive.
57 if (count != 0) {
58 buffer[count] = '\0';
59 std::cout << buffer;
60 }
61 delete[] buffer;
62 }
63
64 G4strstreambuf(const G4strstreambuf&) = delete;
65 G4strstreambuf& operator=(const G4strstreambuf&) = delete;
66
67 G4int overflow(G4int c = EOF) override
68 {
69 G4int result = 0;
70 if (count >= size) result = sync();
71
72 buffer[count] = (char)c;
73 count++;
74
75 return result;
76 }
77
78 G4int sync() override
79 {
80 buffer[count] = '\0';
81 count = 0;
82 return ReceiveString();
83 }
84
85#ifdef WIN32
86 virtual G4int underflow() { return 0; }
87#endif
88
89 void SetDestination(G4coutDestination* dest) { destination = dest; }
90
91 inline G4int ReceiveString()
92 {
93 G4String stringToSend(buffer);
94 if (destination != nullptr) {
95 return DestinationPolicy::PostMessage(destination, stringToSend);
96 }
97 return DefaultPolicy::PostMessage(stringToSend);
98 }
99
100 private:
101 char* buffer = nullptr;
102 G4int count = 0;
103 G4int size = 0;
104 G4coutDestination* destination = nullptr;
105};
106
107// Policies
108struct PostToG4debug
109{
110 static inline G4int PostMessage(G4coutDestination* d, const G4String& s)
111 {
112 return d->ReceiveG4debug_(s);
113 }
114};
115
116struct PostToG4cout
117{
118 static inline G4int PostMessage(G4coutDestination* d, const G4String& s)
119 {
120 return d->ReceiveG4cout_(s);
121 }
122};
123
124struct PostToG4cerr
125{
126 static inline G4int PostMessage(G4coutDestination* d, const G4String& s)
127 {
128 return d->ReceiveG4cerr_(s);
129 }
130};
131
132struct DefaultToCout
133{
134 static inline G4int PostMessage(const G4String& s)
135 {
136 std::cout << s << std::flush;
137 return 0;
138 }
139};
140
141struct DefaultToCerr
142{
143 static inline G4int PostMessage(const G4String& s)
144 {
145 std::cerr << s << std::flush;
146 return 0;
147 }
148};
149
150using G4debugstreambuf = G4strstreambuf<PostToG4debug, DefaultToCout>;
151using G4coutstreambuf = G4strstreambuf<PostToG4cout, DefaultToCout>;
152using G4cerrstreambuf = G4strstreambuf<PostToG4cerr, DefaultToCerr>;
153} // namespace
154
155#ifdef G4MULTITHREADED
156// --- StreamBuffers
157G4debugstreambuf*& _G4debugbuf_p()
158{
159 G4ThreadLocalStatic auto* _instance = new G4debugstreambuf;
160 return _instance;
161}
162
163G4coutstreambuf*& _G4coutbuf_p()
164{
165 G4ThreadLocalStatic auto* _instance = new G4coutstreambuf;
166 return _instance;
167}
168
169G4cerrstreambuf*& _G4cerrbuf_p()
170{
171 G4ThreadLocalStatic auto* _instance = new G4cerrstreambuf;
172 return _instance;
173}
174
175// --- Streams
176std::ostream*& _G4debug_p()
177{
178 G4ThreadLocalStatic auto* _instance = new std::ostream(_G4debugbuf_p());
179 return _instance;
180}
181
182std::ostream*& _G4cout_p()
183{
184 G4ThreadLocalStatic auto* _instance = new std::ostream(_G4coutbuf_p());
185 return _instance;
186}
187
188std::ostream*& _G4cerr_p()
189{
190 G4ThreadLocalStatic auto* _instance = new std::ostream(_G4cerrbuf_p());
191 return _instance;
192}
193
195{
196 // --- Stream Buffers
197 if (_G4debugbuf_p() == nullptr) {
198 _G4debugbuf_p() = new G4debugstreambuf;
199 }
200 if (_G4coutbuf_p() == nullptr) {
201 _G4coutbuf_p() = new G4coutstreambuf;
202 }
203 if (_G4cerrbuf_p() == nullptr) {
204 _G4cerrbuf_p() = new G4cerrstreambuf;
205 }
206
207 // --- Streams
208 if (_G4debug_p() == &std::cout || _G4debug_p() == nullptr) {
209 _G4debug_p() = new std::ostream(_G4debugbuf_p());
210 }
211 if (_G4cout_p() == &std::cout || _G4cout_p() == nullptr) {
212 _G4cout_p() = new std::ostream(_G4coutbuf_p());
213 }
214 if (_G4cerr_p() == &std::cerr || _G4cerr_p() == nullptr) {
215 _G4cerr_p() = new std::ostream(_G4cerrbuf_p());
216 }
217}
218
220{
221 // Reverse order
222 // --- Streams
223 delete _G4debug_p();
224 _G4debug_p() = &std::cout;
225 delete _G4cout_p();
226 _G4cout_p() = &std::cout;
227 delete _G4cerr_p();
228 _G4cerr_p() = &std::cerr;
229
230 // --- Stream Buffers
231 delete _G4debugbuf_p();
232 _G4debugbuf_p() = nullptr;
233 delete _G4coutbuf_p();
234 _G4coutbuf_p() = nullptr;
235 delete _G4cerrbuf_p();
236 _G4cerrbuf_p() = nullptr;
237}
238
239# define G4debugbuf (*_G4debugbuf_p())
240# define G4coutbuf (*_G4coutbuf_p())
241# define G4cerrbuf (*_G4cerrbuf_p())
242
243// These two functions are guaranteed to be called at load and
244// unload of the library containing this code.
245namespace
246{
247# ifndef WIN32
248void setupG4ioSystem() __attribute__((constructor));
249void cleanupG4ioSystem() __attribute__((destructor));
250# endif
251void setupG4ioSystem() { G4iosInitialization(); }
252void cleanupG4ioSystem() { G4iosFinalization(); }
253} // namespace
254
255#else // Sequential
256
257G4debugstreambuf G4debugbuf;
258G4coutstreambuf G4coutbuf;
259G4cerrstreambuf G4cerrbuf;
260
261std::ostream G4debug(&G4debugbuf);
262std::ostream G4cout(&G4coutbuf);
263std::ostream G4cerr(&G4cerrbuf);
264
267
268#endif
269
271{
272 G4debugbuf.SetDestination(sink);
273 G4coutbuf.SetDestination(sink);
274 G4cerrbuf.SetDestination(sink);
275}
int G4int
Definition G4Types.hh:85
G4debugstreambuf G4debugbuf
Definition G4ios.cc:257
void G4iosFinalization()
Definition G4ios.cc:266
void G4iosSetDestination(G4coutDestination *sink)
Definition G4ios.cc:270
G4coutstreambuf G4coutbuf
Definition G4ios.cc:258
G4cerrstreambuf G4cerrbuf
Definition G4ios.cc:259
void G4iosInitialization()
Definition G4ios.cc:265
G4GLOB_DLL std::ostream G4debug
G4GLOB_DLL std::ostream G4cerr
G4GLOB_DLL std::ostream G4cout
G4int ReceiveG4cout_(const G4String &msg)
G4int ReceiveG4debug_(const G4String &msg)
G4int ReceiveG4cerr_(const G4String &msg)
#define G4ThreadLocalStatic
Definition tls.hh:76