Geant4 Cross Reference |
1 // -*- C++ -*- 1 2 // 3 // ------------------------------------------- 4 // HEP Random 5 // --- HepRandom --- 6 // class implementation f 7 // ------------------------------------------- 8 // This file is part of Geant4 (simulation too 9 10 // =========================================== 11 // Gabriele Cosmo - Created: 5th September 199 12 // - Minor corrections: 31st Oc 13 // - Added methods for engine s 14 // - HepRandom defined as singl 15 // kept public for backward c 16 // - Relocated Poisson and Gaus 17 // initialisation of static g 18 // =========================================== 19 20 #include "CLHEP/Random/MixMaxRng.h" 21 #include "CLHEP/Random/Random.h" 22 #include "CLHEP/Random/StaticRandomStates.h" 23 #include "CLHEP/Utility/memory.h" 24 #include "CLHEP/Utility/thread_local.h" 25 #include "CLHEP/Utility/use_atomic.h" 26 27 // ----------------------------- 28 // Static members initialisation 29 // ----------------------------- 30 31 #include "CLHEP/Random/SeedTable.h" 32 33 #include <assert.h> 34 #include <iostream> 35 #include <type_traits> 36 #include <string> 37 38 namespace CLHEP { 39 40 namespace { 41 42 struct defaults { 43 44 defaults() 45 : theGenerator( &theDefaultGenerator, 46 , theEngine ( &theDefaultEngine, do_ 47 { } 48 49 defaults(defaults const& other) = delete 50 defaults const& operator=(defaults const 51 52 void resetEngine( HepRandomEngine * new 53 theEngine.reset( newEngine ); 54 } 55 56 void resetEngine( HepRandomEngine & new 57 theEngine.reset( &newEngine, do_nothin 58 } 59 60 bool ensureInitialized() { 61 assert( theGenerator.get() != 0 && th 62 return true; 63 } 64 65 ~defaults() 66 { } 67 68 private: 69 70 HepRandom theDefaultGenerator; 71 MixMaxRng theDefaultEngine; 72 73 public: 74 75 std::shared_ptr<HepRandom > theGen 76 std::shared_ptr<HepRandomEngine> theEng 77 }; // defaults 78 79 80 #ifdef CLHEP_USE_ATOMIC 81 82 // The ThreadSafeDefaultCache is used only 83 // It is a singly linked list that is inte 84 // type "defaults" per thread. 85 86 class ThreadSafeDefaultsCache { 87 public: 88 89 ThreadSafeDefaultsCache(); 90 91 // The destructor deletes the objects of 92 ~ThreadSafeDefaultsCache(); 93 94 // Creates new objects and adds them to 95 defaults* createNewDefaults(); 96 97 // Note that there are no other function 98 99 private: 100 101 class DefaultsNode { 102 public: 103 DefaultsNode(DefaultsNode* iNext); 104 DefaultsNode const* next() const { ret 105 void setNext(DefaultsNode* v) { next_ 106 defaults* addressOfDefaults() { return 107 private: 108 DefaultsNode* next_; 109 defaults defaults_; 110 }; 111 112 // points to first node in the linked li 113 std::atomic<DefaultsNode*> front_; 114 }; 115 116 ThreadSafeDefaultsCache::ThreadSafeDefault 117 front_(nullptr) { 118 } 119 120 defaults* ThreadSafeDefaultsCache::createN 121 DefaultsNode* expected = front_.load(); 122 DefaultsNode* newNode = new DefaultsNode 123 while (!front_.compare_exchange_strong(e 124 // another thread changed front_ befor 125 newNode->setNext(expected); 126 } 127 return newNode->addressOfDefaults(); 128 } 129 130 ThreadSafeDefaultsCache::DefaultsNode::Def 131 next_(iNext), 132 defaults_() { 133 } 134 135 ThreadSafeDefaultsCache::~ThreadSafeDefaul 136 DefaultsNode const* node = front_.load() 137 while (node) { 138 DefaultsNode const* next = node->next( 139 delete node; 140 node = next; 141 } 142 } 143 144 defaults & theDefaults() { 145 146 // We need to have different engines on 147 // the engines are not thread safe. One 148 // using the same engine on different th 149 // Originally we had the defaults object 150 // but that was failing because on Mac O 151 // support for thread locals yet. Objec 152 // in thread local storage were causing 153 // a container of them that is a functio 154 // and the thread local contains only a 155 // container. 156 static ThreadSafeDefaultsCache defaultsF 157 158 // A pointer for each thread to defaults 159 static CLHEP_THREAD_LOCAL defaults* theD 160 161 return *theDefaults; 162 } 163 #else 164 165 // This version is used with old compilers 166 // In that case, the code should not be ex 167 defaults & theDefaults() { 168 static defaults theDefaults; 169 return theDefaults; 170 } 171 172 #endif 173 174 } // namespace 175 176 //---------------------------- HepRandom ----- 177 178 HepRandom::HepRandom() 179 { } 180 181 HepRandom::HepRandom(long seed) 182 { 183 setTheSeed(seed); 184 } 185 186 HepRandom::HepRandom(HepRandomEngine & algorit 187 { 188 theDefaults().resetEngine( algorithm ); 189 } 190 191 HepRandom::HepRandom(HepRandomEngine * algorit 192 { 193 theDefaults().resetEngine( algorithm ); 194 } 195 196 HepRandom::~HepRandom() 197 { } 198 199 double HepRandom::flat() 200 { 201 return theDefaults().theEngine->flat(); 202 } 203 204 void HepRandom::flatArray(const int size, doub 205 { 206 theDefaults().theEngine->flatArray(size,vect 207 } 208 209 double HepRandom::operator()() { 210 return flat(); 211 } 212 213 std::string HepRandom::name() const {return "H 214 HepRandomEngine & HepRandom::engine() { 215 std::cerr << "HepRandom::engine() called -- 216 return *theDefaults().theEngine.get(); 217 } 218 219 std::ostream & operator<< (std::ostream & os, 220 return dist.put(os); 221 } 222 223 std::istream & operator>> (std::istream & is, 224 return dist.get(is); 225 } 226 227 std::ostream & HepRandom::put(std::ostream & o 228 std::istream & HepRandom::get(std::istream & i 229 230 // -------------------------- 231 // Static methods definitions 232 // -------------------------- 233 234 void HepRandom::setTheSeed(long seed, int lux) 235 { 236 theDefaults().theEngine->setSeed(seed,lux); 237 } 238 239 long HepRandom::getTheSeed() 240 { 241 return theDefaults().theEngine->getSeed(); 242 } 243 244 void HepRandom::setTheSeeds(const long* seeds, 245 { 246 theDefaults().theEngine->setSeeds(seeds,aux) 247 } 248 249 const long* HepRandom::getTheSeeds () 250 { 251 return theDefaults().theEngine->getSeeds(); 252 } 253 254 void HepRandom::getTheTableSeeds(long* seeds, 255 { 256 if ((index >= 0) && (index < 215)) { 257 seeds[0] = seedTable[index][0]; 258 seeds[1] = seedTable[index][1]; 259 } 260 else seeds = NULL; 261 } 262 263 HepRandom * HepRandom::getTheGenerator() 264 { 265 return theDefaults().theGenerator.get(); 266 } 267 268 HepRandomEngine * HepRandom::getTheEngine() 269 { 270 return theDefaults().theEngine.get(); 271 } 272 273 void HepRandom::setTheEngine (HepRandomEngine* 274 { 275 theDefaults().theEngine.reset( theNewEngine, 276 } 277 278 void HepRandom::saveEngineStatus( const char f 279 { 280 theDefaults().theEngine->saveStatus( filenam 281 } 282 283 void HepRandom::restoreEngineStatus( const cha 284 { 285 theDefaults().theEngine->restoreStatus( file 286 } 287 288 std::ostream& HepRandom::saveFullState ( std:: 289 os << *getTheEngine(); 290 return os; 291 } 292 293 std::istream& HepRandom::restoreFullState ( st 294 is >> *getTheEngine(); 295 return is; 296 } 297 298 std::ostream& HepRandom::saveStaticRandomState 299 return StaticRandomStates::save(os); 300 } 301 302 std::istream& HepRandom::restoreStaticRandomSt 303 return StaticRandomStates::restore(is); 304 } 305 306 void HepRandom::showEngineStatus() 307 { 308 theDefaults().theEngine->showStatus(); 309 } 310 311 int HepRandom::createInstance() 312 { 313 return static_cast<int>( theDefaults().ensur 314 } 315 316 } // namespace CLHEP 317