Geant4 Cross Reference |
1 // 1 2 // ******************************************* 3 // * License and Disclaimer 4 // * 5 // * The Geant4 software is copyright of th 6 // * the Geant4 Collaboration. It is provided 7 // * conditions of the Geant4 Software License 8 // * LICENSE and available at http://cern.ch/ 9 // * include a list of copyright holders. 10 // * 11 // * Neither the authors of this software syst 12 // * institutes,nor the agencies providing fin 13 // * work make any representation or warran 14 // * regarding this software system or assum 15 // * use. Please see the license in the file 16 // * for the full disclaimer and the limitatio 17 // * 18 // * This code implementation is the result 19 // * technical work of the GEANT4 collaboratio 20 // * By using, copying, modifying or distri 21 // * any work based on the software) you ag 22 // * use in resulting scientific publicati 23 // * acceptance of all terms of the Geant4 Sof 24 // ******************************************* 25 // 26 // G4ThreadLocalSingleton 27 // 28 // Class description: 29 // 30 // This class implements a thread-private "sin 31 // private the singleton is not a singleton in 32 // instance exists for each thread. 33 // This class is a wrapper around the real obj 34 // make singleton. 35 // 36 // Limitation: 37 // The object that is made thread-private si 38 // contain any thread-local data member. Not 39 // if an object is to be thread-private it i 40 // any data-member as G4ThreadLocal. 41 // 42 // Performance issues: 43 // This class uses locks and mutexes. 44 // 45 // Example: 46 // This is the singleton pattern often found 47 // class G4Class 48 // { 49 // private: 50 // static G4Class* instance; 51 // G4Class() { ... } 52 // public: 53 // static G4Class* GetInstance() 54 // { 55 // static G4Class theInstance; 56 // if ( instance == nullptr ) instance 57 // return instance; 58 // } 59 // }; 60 // This is transformed to the following to i 61 // singleton: 62 // class G4Class 63 // { 64 // private: 65 // static G4ThreadLocal G4Class* instanc 66 // G4Class() { ... } 67 // public: 68 // static G4Class* GetInstance() 69 // { 70 // if ( instance == nullptr ) instance 71 // return instance; 72 // } 73 // }; 74 // Note that this class also has a memory le 75 // 76 // This class can be used as follows: 77 // class G4Class 78 // { 79 // friend class G4ThreadLocalSingleton<G4C 80 // private: 81 // G4Class() { ... } 82 // public: 83 // static G4Class* GetInstance() 84 // { 85 // static G4ThreadLocalSingleton<G4Cla 86 // return instance.Instance(); 87 // } 88 // }; 89 // Each thread has its own instance of G4Cla 90 // Deletion of G4Class instances is done at 91 // Note the "friend" statement. 92 93 // Author: A.Dotti, 28 October 2013 94 // ------------------------------------------- 95 #ifndef G4TLSSINGLETON_HH 96 #define G4TLSSINGLETON_HH 1 97 98 #include "G4AutoLock.hh" 99 #include "G4Cache.hh" 100 #include "G4Backtrace.hh" 101 #include "G4Threading.hh" 102 103 #include <list> 104 #include <vector> 105 #include <functional> 106 107 // Forward declaration. See G4AutoDelete.hh 108 // 109 namespace G4AutoDelete 110 { 111 template <class T> 112 void Register(T*); 113 } 114 115 template <class T> 116 class G4ThreadLocalSingleton; 117 118 // this explicit specialization holds all the 119 // to explicitly invoke the auto-deletion 120 template <> 121 class G4ThreadLocalSingleton<void> 122 { 123 private: 124 using fvector_t = std::vector<std::function< 125 126 template <class T> 127 friend class G4ThreadLocalSingleton; 128 129 static fvector_t& GetCallbacks(); 130 static G4Mutex& GetMutex(); 131 132 public: 133 static void Clear(); 134 135 template <typename FuncT> 136 static typename fvector_t::iterator Insert(F 137 { 138 G4AutoLock _lk{ GetMutex() }; 139 return GetCallbacks().emplace(GetCallbacks 140 std::forward 141 } 142 }; 143 144 template <class T> 145 class G4ThreadLocalSingleton : private G4Cache 146 { 147 friend void G4AutoDelete::Register<T>(T*); 148 149 public: 150 G4ThreadLocalSingleton(); 151 // Creates thread-local singleton manager 152 153 ~G4ThreadLocalSingleton() override; 154 155 G4ThreadLocalSingleton(const G4ThreadLocalSi 156 G4ThreadLocalSingleton(G4ThreadLocalSingleto 157 158 G4ThreadLocalSingleton& operator=(const G4Th 159 G4ThreadLocalSingleton& operator=(G4ThreadLo 160 161 T* Instance() const; 162 // Returns a pointer to a thread-private ins 163 164 private: 165 void Register(T* i) const; 166 167 void Clear(); 168 169 mutable std::list<T*> instances; 170 mutable G4Mutex listm; 171 }; 172 173 //============================================ 174 // Inline methods implementation 175 //============================================ 176 177 template <class T> 178 G4ThreadLocalSingleton<T>::G4ThreadLocalSingle 179 : G4Cache<T*>() 180 { 181 G4MUTEXINIT(listm); 182 G4Cache<T*>::Put(nullptr); 183 // Uncomment below to find the origin of whe 184 /* 185 auto bt = G4Backtrace::GetDemangled<4, 1>( 186 [](const char* cstr) { return std::string{ 187 std::cout << "Backtrace to G4ThreadLocalSing 188 << G4Demangle<T>().c_str() << ">:\ 189 for(auto& itr : bt) 190 { 191 if(!itr.empty()) 192 std::cout << "\t" << itr << "\n"; 193 } 194 */ 195 G4ThreadLocalSingleton<void>::Insert([&]() { 196 // printf("Deleting G4ThreadLocalSingleton 197 // G4Demangle<T>().c_str()); 198 this->Clear(); 199 }); 200 } 201 202 template <class T> 203 G4ThreadLocalSingleton<T>::~G4ThreadLocalSingl 204 { 205 Clear(); 206 G4MUTEXDESTROY(listm); 207 } 208 209 template <class T> 210 T* G4ThreadLocalSingleton<T>::Instance() const 211 { 212 T* instance = G4Cache<T*>::Get(); 213 if(instance == static_cast<T*>(0)) 214 { 215 instance = new T; 216 G4Cache<T*>::Put(instance); 217 Register(instance); 218 } 219 return instance; 220 } 221 222 template <class T> 223 void G4ThreadLocalSingleton<T>::Register(T* i) 224 { 225 G4AutoLock l(&listm); 226 instances.push_back(i); 227 } 228 229 template <class T> 230 void G4ThreadLocalSingleton<T>::Clear() 231 { 232 if(instances.empty()) 233 return; 234 G4AutoLock l(&listm); 235 while(!instances.empty()) 236 { 237 T* thisinst = instances.front(); 238 instances.pop_front(); 239 delete thisinst; 240 } 241 } 242 243 #endif 244