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 // 29 // ------------------------------------------- << 28 // >> 29 // -------------------------------------------------------------- >> 30 // GEANT 4 class implementation file >> 31 // >> 32 // G4ios.cc >> 33 // >> 34 // History 1998 Nov. 3 Masayasu Nagamatu 30 35 31 #include "G4ios.hh" 36 #include "G4ios.hh" 32 << 37 #include "G4strstreambuf.hh" 33 #include "G4coutDestination.hh" << 34 << 35 #include <iostream> 38 #include <iostream> 36 39 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 << 149 #ifdef G4MULTITHREADED 40 #ifdef G4MULTITHREADED 150 // --- StreamBuffers << 151 G4debugstreambuf*& _G4debugbuf_p() << 152 { << 153 G4ThreadLocalStatic auto* _instance = new G4 << 154 return _instance; << 155 } << 156 << 157 G4coutstreambuf*& _G4coutbuf_p() << 158 { << 159 G4ThreadLocalStatic auto* _instance = new G4 << 160 return _instance; << 161 } << 162 41 163 G4cerrstreambuf*& _G4cerrbuf_p() << 42 G4strstreambuf*& _G4coutbuf_p() 164 { 43 { 165 G4ThreadLocalStatic auto* _instance = new G4 << 44 G4ThreadLocalStatic G4strstreambuf* _instance = new G4strstreambuf(); 166 return _instance; << 45 return _instance; 167 } 46 } 168 47 169 // --- Streams << 48 G4strstreambuf*& _G4cerrbuf_p() 170 std::ostream*& _G4debug_p() << 171 { 49 { 172 G4ThreadLocalStatic auto* _instance = new st << 50 G4ThreadLocalStatic G4strstreambuf* _instance = new G4strstreambuf(); 173 return _instance; << 51 return _instance; 174 } 52 } 175 53 176 std::ostream*& _G4cout_p() 54 std::ostream*& _G4cout_p() 177 { 55 { 178 G4ThreadLocalStatic auto* _instance = new st << 56 G4ThreadLocalStatic std::ostream* _instance = new std::ostream(_G4coutbuf_p()); 179 return _instance; << 57 return _instance; 180 } 58 } 181 59 182 std::ostream*& _G4cerr_p() 60 std::ostream*& _G4cerr_p() 183 { 61 { 184 G4ThreadLocalStatic auto* _instance = new st << 62 G4ThreadLocalStatic std::ostream* _instance = new std::ostream(_G4cerrbuf_p()); 185 return _instance; << 63 return _instance; 186 } 64 } 187 65 >> 66 #define G4coutbuf (*_G4coutbuf_p()) >> 67 #define G4cerrbuf (*_G4cerrbuf_p()) >> 68 #define G4cout (*_G4cout_p()) >> 69 #define G4cerr (*_G4cerr_p()) >> 70 188 void G4iosInitialization() 71 void G4iosInitialization() 189 { 72 { 190 // --- Stream Buffers << 73 if (_G4coutbuf_p() == 0) _G4coutbuf_p() = new G4strstreambuf; 191 if (_G4debugbuf_p() == nullptr) { << 74 if (_G4cerrbuf_p() == 0) _G4cerrbuf_p() = new G4strstreambuf; 192 _G4debugbuf_p() = new G4debugstreambuf; << 75 if (_G4cout_p() == &std::cout || _G4cout_p() == 0) _G4cout_p() = new std::ostream(_G4coutbuf_p()); 193 } << 76 if (_G4cerr_p() == &std::cerr || _G4cerr_p() == 0) _G4cerr_p() = new std::ostream(_G4cerrbuf_p()); 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 } << 211 } 77 } 212 78 213 void G4iosFinalization() 79 void G4iosFinalization() 214 { 80 { 215 // Reverse order << 81 delete _G4cout_p(); _G4cout_p() = &std::cout; 216 // --- Flush << 82 delete _G4cerr_p(); _G4cerr_p() = &std::cerr; 217 _G4debug_p()->flush(); << 83 delete _G4coutbuf_p(); _G4coutbuf_p() = nullptr; 218 _G4cout_p()->flush(); << 84 delete _G4cerrbuf_p(); _G4cerrbuf_p() = nullptr; 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 } 85 } 237 86 238 # define G4debugbuf (*_G4debugbuf_p()) << 87 // These two functions are guaranteed to be called at load and 239 # define G4coutbuf (*_G4coutbuf_p()) << 88 // unload of the library containing this code. 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 89 namespace 264 { 90 { 265 struct RAII_G4iosSystem { << 91 #ifndef WIN32 266 RAII_G4iosSystem() { << 92 void setupG4ioSystem(void) __attribute__ ((constructor)); 267 G4iosInitialization(); << 93 void cleanupG4ioSystem(void) __attribute__((destructor)); 268 } << 94 #endif 269 ~RAII_G4iosSystem() { << 95 void setupG4ioSystem(void) { G4iosInitialization(); } 270 G4iosFinalization(); << 96 void cleanupG4ioSystem(void) { G4iosFinalization(); } 271 } << 97 } 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 98 278 #else // Sequential 99 #else // Sequential 279 100 280 G4debugstreambuf G4debugbuf; << 101 G4strstreambuf G4coutbuf; 281 G4coutstreambuf G4coutbuf; << 102 G4strstreambuf G4cerrbuf; 282 G4cerrstreambuf G4cerrbuf; << 283 << 284 std::ostream G4debug(&G4debugbuf); << 285 std::ostream G4cout(&G4coutbuf); 103 std::ostream G4cout(&G4coutbuf); 286 std::ostream G4cerr(&G4cerrbuf); 104 std::ostream G4cerr(&G4cerrbuf); 287 105 288 void G4iosInitialization() {} 106 void G4iosInitialization() {} 289 void G4iosFinalization() { << 107 void G4iosFinalization() {} 290 G4debug.flush(); << 291 G4cout.flush(); << 292 G4cerr.flush(); << 293 } << 294 108 295 #endif 109 #endif 296 << 297 void G4iosSetDestination(G4coutDestination* si << 298 { << 299 G4debugbuf.SetDestination(sink); << 300 G4coutbuf.SetDestination(sink); << 301 G4cerrbuf.SetDestination(sink); << 302 } << 303 110