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