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 // G4ThreadLocalSingleton << 26 // $Id$ 27 // 27 // 28 // Class description: << 28 // --------------------------------------------------------------- >> 29 // GEANT 4 class header file 29 // 30 // 30 // This class implements a thread-private "sin << 31 // Class Description: 31 // private the singleton is not a singleton in << 32 // This class implements a thread-private "singleton". Being thread 32 // instance exists for each thread. << 33 // private the singleton is not a singleton in the term, but a different 33 // This class is a wrapper around the real obj << 34 // instance existis for each thread. 34 // make singleton. << 35 // This class is a wrapper around the real object that we need to >> 36 // make singleton. 35 // 37 // 36 // Limitation: 38 // Limitation: 37 // The object that is made thread-private si << 39 // The object that is made thread-private singleton, should not 38 // contain any thread-local data member. Not << 40 // contain any G4ThreadLocal data member. Note that in general, 39 // if an object is to be thread-private it i << 41 // if object is to be thread-private it is unnecessary to mark 40 // any data-member as G4ThreadLocal. 42 // any data-member as G4ThreadLocal. 41 // << 43 // 42 // Performance issues: 44 // Performance issues: 43 // This class uses locks and mutexes. 45 // This class uses locks and mutexes. 44 // 46 // 45 // Example: 47 // Example: 46 // This is the singleton pattern often found << 48 // This is the singleton patter often found in G4 (sequential): 47 // class G4Class << 49 // class G4Class { 48 // { << 50 // private: 49 // private: << 51 // static G4Class* instance; 50 // static G4Class* instance; << 52 // G4Class() { ... } 51 // G4Class() { ... } << 53 // public: 52 // public: << 54 // static G4Class* GetInstance() { 53 // static G4Class* GetInstance() << 55 // static G4Class theInstance; 54 // { << 56 // if ( instance == 0 ) instance = &theInstance; 55 // static G4Class theInstance; << 57 // return instance; 56 // if ( instance == nullptr ) instance << 58 // } 57 // return instance; << 59 // }; 58 // } << 60 // This is transformed to the following to implement a thread-local 59 // }; << 61 // singleton: 60 // This is transformed to the following to i << 62 // class G4Class { 61 // singleton: << 63 // private: 62 // class G4Class << 64 // static G4ThreadLocal G4Class* instance; 63 // { << 65 // G4Class() { ... } 64 // private: << 66 // public: 65 // static G4ThreadLocal G4Class* instanc << 67 // static G4Class* GetInstance() { 66 // G4Class() { ... } << 68 // if ( instance == 0 ) instance = new G4Class; 67 // public: << 69 // return instance; 68 // static G4Class* GetInstance() << 70 // } 69 // { << 71 // }; 70 // if ( instance == nullptr ) instance << 72 // Note that this class also has a memory leak. 71 // return instance; << 73 // 72 // } << 74 // This class can be used as follows: 73 // }; << 75 // class G4Class { 74 // Note that this class also has a memory le << 76 // friend class G4ThreadLocalSingleton<G4Class>; 75 // << 77 // private: 76 // This class can be used as follows: << 78 // G4Class() { ... } 77 // class G4Class << 79 // public: 78 // { << 80 // static G4Class* GetInstance() { 79 // friend class G4ThreadLocalSingleton<G4C << 81 // static G4ThreadLocalSingleton<G4Class> instance; 80 // private: << 82 // return instance.Instance(); 81 // G4Class() { ... } << 83 // } 82 // public: << 84 // }; 83 // static G4Class* GetInstance() << 85 // Each thread has its own instance of G4Class. 84 // { << 86 // Deletion of G4Class instances is done at end of program. 85 // static G4ThreadLocalSingleton<G4Cla << 87 // Note the "friend" statement. 86 // return instance.Instance(); << 88 // 87 // } << 89 // History: 88 // }; << 90 // 28 October 2013: A. Dotti - First implementation 89 // Each thread has its own instance of G4Cla << 90 // Deletion of G4Class instances is done at << 91 // Note the "friend" statement. << 92 91 93 // Author: A.Dotti, 28 October 2013 << 94 // ------------------------------------------- << 95 #ifndef G4TLSSINGLETON_HH 92 #ifndef G4TLSSINGLETON_HH 96 #define G4TLSSINGLETON_HH 1 << 93 #define G4TLSSINGLETON_HH 97 94 98 #include "G4AutoLock.hh" << 95 //Debug this code 99 #include "G4Cache.hh" << 96 //#define g4tlssdebug 1 100 #include "G4Backtrace.hh" << 101 #include "G4Threading.hh" << 102 97 >> 98 #include "G4Cache.hh" 103 #include <list> 99 #include <list> 104 #include <vector> << 105 #include <functional> << 106 100 107 // Forward declaration. See G4AutoDelete.hh << 101 //Forward declaration. See G4AutoDelete.hh 108 // << 102 namespace G4AutoDelete { 109 namespace G4AutoDelete << 103 template<class T> 110 { << 111 template <class T> << 112 void Register(T*); 104 void Register(T*); 113 } 105 } 114 106 115 template <class T> << 107 template<class T> 116 class G4ThreadLocalSingleton; << 108 class G4ThreadLocalSingleton : private G4Cache<T*> { 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*); 109 friend void G4AutoDelete::Register<T>(T*); 148 << 110 public: 149 public: << 150 G4ThreadLocalSingleton(); 111 G4ThreadLocalSingleton(); 151 // Creates thread-local singleton manager << 112 //Creates thread-local singleton manager 152 113 153 ~G4ThreadLocalSingleton() override; << 114 ~G4ThreadLocalSingleton(); 154 115 155 G4ThreadLocalSingleton(const G4ThreadLocalSi << 116 T* Instance() const; 156 G4ThreadLocalSingleton(G4ThreadLocalSingleto << 117 //Returns a pointer to a thread-private instance of T 157 118 158 G4ThreadLocalSingleton& operator=(const G4Th << 119 private: 159 G4ThreadLocalSingleton& operator=(G4ThreadLo << 120 G4ThreadLocalSingleton( G4ThreadLocalSingleton& rhs);// {} 160 << 121 void Register(T* i) const; 161 T* Instance() const; << 162 // Returns a pointer to a thread-private ins << 163 << 164 private: << 165 void Register(T* i) const; << 166 122 167 void Clear(); 123 void Clear(); 168 124 169 mutable std::list<T*> instances; 125 mutable std::list<T*> instances; 170 mutable G4Mutex listm; 126 mutable G4Mutex listm; 171 }; 127 }; 172 128 >> 129 173 //============================================ 130 //============================================================= 174 // Inline methods implementation << 131 // Implementation details follow 175 //============================================ 132 //============================================================= 176 << 133 #include "G4AutoLock.hh" 177 template <class T> << 134 template<class T> 178 G4ThreadLocalSingleton<T>::G4ThreadLocalSingle << 135 G4ThreadLocalSingleton<T>::G4ThreadLocalSingleton() : G4Cache<T*>() { 179 : G4Cache<T*>() << 180 { << 181 G4MUTEXINIT(listm); 136 G4MUTEXINIT(listm); 182 G4Cache<T*>::Put(nullptr); << 137 G4Cache<T*>::Put(static_cast<T*>(0)); 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 } 138 } 201 139 202 template <class T> << 140 template<class T> 203 G4ThreadLocalSingleton<T>::~G4ThreadLocalSingl << 141 G4ThreadLocalSingleton<T>::~G4ThreadLocalSingleton() { 204 { << 205 Clear(); 142 Clear(); 206 G4MUTEXDESTROY(listm); 143 G4MUTEXDESTROY(listm); 207 } 144 } 208 145 209 template <class T> << 146 template<class T> 210 T* G4ThreadLocalSingleton<T>::Instance() const << 147 T* G4ThreadLocalSingleton<T>::Instance() const { 211 { << 148 T* instance = G4Cache<T*>::Get(); 212 T* instance = G4Cache<T*>::Get(); << 149 if ( instance == static_cast<T*>(0) ) { 213 if(instance == static_cast<T*>(0)) << 150 instance = new T; 214 { << 151 G4Cache<T*>::Put( instance ); 215 instance = new T; << 152 Register(instance); 216 G4Cache<T*>::Put(instance); << 153 } 217 Register(instance); << 154 return instance; 218 } 155 } 219 return instance; << 220 } << 221 156 222 template <class T> << 157 template<class T> 223 void G4ThreadLocalSingleton<T>::Register(T* i) << 158 G4ThreadLocalSingleton<T>::G4ThreadLocalSingleton( G4ThreadLocalSingleton&) {} 224 { << 159 template<class T> >> 160 void G4ThreadLocalSingleton<T>::Register(T* i) const { 225 G4AutoLock l(&listm); 161 G4AutoLock l(&listm); 226 instances.push_back(i); 162 instances.push_back(i); 227 } 163 } 228 164 229 template <class T> << 165 230 void G4ThreadLocalSingleton<T>::Clear() << 166 template<class T> 231 { << 167 void G4ThreadLocalSingleton<T>::Clear() { 232 if(instances.empty()) << 168 G4AutoLock l(&listm); 233 return; << 169 while ( ! instances.empty() ) 234 G4AutoLock l(&listm); << 170 { 235 while(!instances.empty()) << 171 T* thisinst = instances.front(); 236 { << 172 instances.pop_front(); 237 T* thisinst = instances.front(); << 173 if ( thisinst != 0 ) delete thisinst; 238 instances.pop_front(); << 174 } 239 delete thisinst; << 240 } 175 } 241 } << 242 176 243 #endif << 177 #endif //G4TLSSINGLETON_HH 244 178