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 // G4ios implementation << 27 // 26 // 28 // Authors: H.Yoshida, M.Nagamatu - November 1 << 27 // $Id: G4ios.cc 79149 2014-02-19 15:08:06Z gcosmo $ 29 // ------------------------------------------- << 28 // >> 29 // >> 30 // -------------------------------------------------------------- >> 31 // GEANT 4 class implementation file >> 32 // >> 33 // G4ios.cc >> 34 // >> 35 // History 1998 Nov. 3 Masayasu Nagamatu 30 36 31 #include "G4ios.hh" 37 #include "G4ios.hh" 32 << 38 #include "G4strstreambuf.hh" 33 #include "G4coutDestination.hh" << 34 << 35 #include <iostream> << 36 << 37 namespace << 38 { << 39 // Concrete streambuf redirecting output to G4 << 40 // Templated on two policy types to determine: << 41 // - DestinationPolicy: which member member fu << 42 // - DefaultPolicy: what to do if G4coutDestin << 43 template <typename DestinationPolicy, typename << 44 class G4strstreambuf : public std::basic_strea << 45 { << 46 public: << 47 G4strstreambuf() << 48 { << 49 size = 4095; << 50 buffer = new char[size + 1]; << 51 } << 52 << 53 ~G4strstreambuf() override << 54 { << 55 delete[] buffer; << 56 } << 57 << 58 G4strstreambuf(const G4strstreambuf&) = dele << 59 G4strstreambuf& operator=(const G4strstreamb << 60 << 61 G4int overflow(G4int c = EOF) override << 62 { << 63 G4int result = 0; << 64 if (count >= size) result = sync(); << 65 << 66 buffer[count] = (char)c; << 67 count++; << 68 << 69 return result; << 70 } << 71 << 72 G4int sync() override << 73 { << 74 buffer[count] = '\0'; << 75 count = 0; << 76 return ReceiveString(); << 77 } << 78 << 79 #ifdef WIN32 << 80 virtual G4int underflow() { return 0; } << 81 #endif << 82 << 83 void SetDestination(G4coutDestination* dest) << 84 << 85 inline G4int ReceiveString() << 86 { << 87 G4String stringToSend(buffer); << 88 if (destination != nullptr) { << 89 return DestinationPolicy::PostMessage(de << 90 } << 91 return DefaultPolicy::PostMessage(stringTo << 92 } << 93 << 94 private: << 95 char* buffer = nullptr; << 96 G4int count = 0; << 97 G4int size = 0; << 98 G4coutDestination* destination = nullptr; << 99 }; << 100 << 101 // Policies << 102 struct PostToG4debug << 103 { << 104 static inline G4int PostMessage(G4coutDestin << 105 { << 106 return d->ReceiveG4debug_(s); << 107 } << 108 }; << 109 << 110 struct PostToG4cout << 111 { << 112 static inline G4int PostMessage(G4coutDestin << 113 { << 114 return d->ReceiveG4cout_(s); << 115 } << 116 }; << 117 << 118 struct PostToG4cerr << 119 { << 120 static inline G4int PostMessage(G4coutDestin << 121 { << 122 return d->ReceiveG4cerr_(s); << 123 } << 124 }; << 125 << 126 struct DefaultToCout << 127 { << 128 static inline G4int PostMessage(const G4Stri << 129 { << 130 std::cout << s << std::flush; << 131 return 0; << 132 } << 133 }; << 134 << 135 struct DefaultToCerr << 136 { << 137 static inline G4int PostMessage(const G4Stri << 138 { << 139 std::cerr << s << std::flush; << 140 return 0; << 141 } << 142 }; << 143 << 144 using G4debugstreambuf = G4strstreambuf<PostTo << 145 using G4coutstreambuf = G4strstreambuf<PostToG << 146 using G4cerrstreambuf = G4strstreambuf<PostToG << 147 } // namespace << 148 39 149 #ifdef G4MULTITHREADED 40 #ifdef G4MULTITHREADED 150 // --- StreamBuffers << 41 G4ThreadLocal G4strstreambuf *G4coutbuf_p = 0; 151 G4debugstreambuf*& _G4debugbuf_p() << 42 G4ThreadLocal G4strstreambuf *G4cerrbuf_p = 0; 152 { << 43 G4ThreadLocal std::ostream *G4cout_p = 0; 153 G4ThreadLocalStatic auto* _instance = new G4 << 44 G4ThreadLocal std::ostream *G4cerr_p = 0; 154 return _instance; << 45 #define G4coutbuf (*G4coutbuf_p) 155 } << 46 #define G4cerrbuf (*G4cerrbuf_p) 156 << 47 #define G4cout (*G4cout_p) 157 G4coutstreambuf*& _G4coutbuf_p() << 48 #define G4cerr (*G4cerr_p) 158 { << 49 159 G4ThreadLocalStatic auto* _instance = new G4 << 50 void G4iosInitialization() 160 return _instance; << 51 { 161 } << 52 if (G4coutbuf_p == 0) G4coutbuf_p = new G4strstreambuf; 162 << 53 if (G4cerrbuf_p == 0) G4cerrbuf_p = new G4strstreambuf; 163 G4cerrstreambuf*& _G4cerrbuf_p() << 54 if (G4cout_p == 0) G4cout_p = new std::ostream(G4coutbuf_p); 164 { << 55 if (G4cerr_p == 0) G4cerr_p = new std::ostream(G4cerrbuf_p); 165 G4ThreadLocalStatic auto* _instance = new G4 << 56 } 166 return _instance; << 57 167 } << 58 void G4iosFinalization() 168 << 59 { 169 // --- Streams << 60 delete G4cout_p; G4cout_p = 0; 170 std::ostream*& _G4debug_p() << 61 delete G4cerr_p; G4cerr_p = 0; 171 { << 62 delete G4coutbuf_p; G4coutbuf_p = 0; 172 G4ThreadLocalStatic auto* _instance = new st << 63 delete G4cerrbuf_p; G4cerrbuf_p = 0; 173 return _instance; << 64 } 174 } << 65 175 << 66 // These two functions are guaranteed to be called at load and 176 std::ostream*& _G4cout_p() << 67 // unload of the library containing this code. 177 { << 68 namespace 178 G4ThreadLocalStatic auto* _instance = new st << 69 { 179 return _instance; << 70 #ifndef WIN32 180 } << 71 void setupG4ioSystem(void) __attribute__ ((constructor)); 181 << 72 void cleanupG4ioSystem(void) __attribute__((destructor)); 182 std::ostream*& _G4cerr_p() << 73 #endif 183 { << 74 void setupG4ioSystem(void) { G4iosInitialization(); } 184 G4ThreadLocalStatic auto* _instance = new st << 75 void cleanupG4ioSystem(void) { G4iosFinalization(); } 185 return _instance; << 186 } << 187 << 188 void G4iosInitialization() << 189 { << 190 // --- Stream Buffers << 191 if (_G4debugbuf_p() == nullptr) { << 192 _G4debugbuf_p() = new G4debugstreambuf; << 193 } << 194 if (_G4coutbuf_p() == nullptr) { << 195 _G4coutbuf_p() = new G4coutstreambuf; << 196 } << 197 if (_G4cerrbuf_p() == nullptr) { << 198 _G4cerrbuf_p() = new G4cerrstreambuf; << 199 } << 200 << 201 // --- Streams << 202 if (_G4debug_p() == &std::cout || _G4debug_p << 203 _G4debug_p() = new std::ostream(_G4debugbu << 204 } << 205 if (_G4cout_p() == &std::cout || _G4cout_p() << 206 _G4cout_p() = new std::ostream(_G4coutbuf_ << 207 } << 208 if (_G4cerr_p() == &std::cerr || _G4cerr_p() << 209 _G4cerr_p() = new std::ostream(_G4cerrbuf_ << 210 } 76 } 211 } << 212 << 213 void G4iosFinalization() << 214 { << 215 // Reverse order << 216 // --- Flush << 217 _G4debug_p()->flush(); << 218 _G4cout_p()->flush(); << 219 _G4cerr_p()->flush(); << 220 << 221 // --- Streams << 222 delete _G4debug_p(); << 223 _G4debug_p() = &std::cout; << 224 delete _G4cout_p(); << 225 _G4cout_p() = &std::cout; << 226 delete _G4cerr_p(); << 227 _G4cerr_p() = &std::cerr; << 228 << 229 // --- Stream Buffers << 230 delete _G4debugbuf_p(); << 231 _G4debugbuf_p() = nullptr; << 232 delete _G4coutbuf_p(); << 233 _G4coutbuf_p() = nullptr; << 234 delete _G4cerrbuf_p(); << 235 _G4cerrbuf_p() = nullptr; << 236 } << 237 << 238 # define G4debugbuf (*_G4debugbuf_p()) << 239 # define G4coutbuf (*_G4coutbuf_p()) << 240 # define G4cerrbuf (*_G4cerrbuf_p()) << 241 << 242 // We want to trigger initialization at load t << 243 // finalization at unloading time. Directly m << 244 // the `.init/.fini` section using the `__attr << 245 // (beside that it does not work on Windows) d << 246 // where Geant4 is built with static libraries << 247 // package is built with shared library and ha << 248 // that are linking against those shared libra << 249 // to the Geant4 static libraries (for example << 250 // code calls Geant4 directly in addition to i << 251 // the shared library). << 252 // In this example, the explicit `.init/.fini` << 253 // added twice (because the linker is asked to << 254 // file twice and each time needs to add the i << 255 // This issue appear also for the initializati << 256 // including those declared as function static << 257 // To get the behavior we need (where the G4io << 258 // and G4iosFinalization are called exactly on << 259 // associate the initialization with a symbol << 260 // the linker is told to de-duplicate even in << 261 // above. So we use an extern object that is << 262 // initialized once. << 263 namespace << 264 { << 265 struct RAII_G4iosSystem { << 266 RAII_G4iosSystem() { << 267 G4iosInitialization(); << 268 } << 269 ~RAII_G4iosSystem() { << 270 G4iosFinalization(); << 271 } << 272 }; << 273 } // namespace << 274 // Extern but not user reachable (anonymous ty << 275 // We want the linker to only create one of th << 276 extern "C" RAII_G4iosSystem RAII_G4iosSystemOb << 277 77 278 #else // Sequential 78 #else // Sequential 279 79 280 G4debugstreambuf G4debugbuf; << 80 G4strstreambuf G4coutbuf; 281 G4coutstreambuf G4coutbuf; << 81 G4strstreambuf G4cerrbuf; 282 G4cerrstreambuf G4cerrbuf; << 82 std::ostream G4cout(&G4coutbuf); 283 << 83 std::ostream G4cerr(&G4cerrbuf); 284 std::ostream G4debug(&G4debugbuf); << 285 std::ostream G4cout(&G4coutbuf); << 286 std::ostream G4cerr(&G4cerrbuf); << 287 84 288 void G4iosInitialization() {} << 85 void G4iosInitialization() {} 289 void G4iosFinalization() { << 86 void G4iosFinalization() {} 290 G4debug.flush(); << 291 G4cout.flush(); << 292 G4cerr.flush(); << 293 } << 294 87 295 #endif 88 #endif 296 << 297 void G4iosSetDestination(G4coutDestination* si << 298 { << 299 G4debugbuf.SetDestination(sink); << 300 G4coutbuf.SetDestination(sink); << 301 G4cerrbuf.SetDestination(sink); << 302 } << 303 89