|
||||
File indexing completed on 2025-01-18 09:59:11
0001 // 0002 // ******************************************************************** 0003 // * License and Disclaimer * 0004 // * * 0005 // * The Geant4 software is copyright of the Copyright Holders of * 0006 // * the Geant4 Collaboration. It is provided under the terms and * 0007 // * conditions of the Geant4 Software License, included in the file * 0008 // * LICENSE and available at http://cern.ch/geant4/license . These * 0009 // * include a list of copyright holders. * 0010 // * * 0011 // * Neither the authors of this software system, nor their employing * 0012 // * institutes,nor the agencies providing financial support for this * 0013 // * work make any representation or warranty, express or implied, * 0014 // * regarding this software system or assume any liability for its * 0015 // * use. Please see the license in the file LICENSE and URL above * 0016 // * for the full disclaimer and the limitation of liability. * 0017 // * * 0018 // * This code implementation is the result of the scientific and * 0019 // * technical work of the GEANT4 collaboration. * 0020 // * By using, copying, modifying or distributing the software (or * 0021 // * any work based on the software) you agree to acknowledge its * 0022 // * use in resulting scientific publications, and indicate your * 0023 // * acceptance of all terms of the Geant4 Software license. * 0024 // ******************************************************************** 0025 // 0026 // G4ThreadLocalSingleton 0027 // 0028 // Class description: 0029 // 0030 // This class implements a thread-private "singleton". Being thread 0031 // private the singleton is not a singleton in the term, but a different 0032 // instance exists for each thread. 0033 // This class is a wrapper around the real object that we need to 0034 // make singleton. 0035 // 0036 // Limitation: 0037 // The object that is made thread-private singleton should not 0038 // contain any thread-local data member. Note that in general, 0039 // if an object is to be thread-private it is unnecessary to mark 0040 // any data-member as G4ThreadLocal. 0041 // 0042 // Performance issues: 0043 // This class uses locks and mutexes. 0044 // 0045 // Example: 0046 // This is the singleton pattern often found in Geant4 (sequential): 0047 // class G4Class 0048 // { 0049 // private: 0050 // static G4Class* instance; 0051 // G4Class() { ... } 0052 // public: 0053 // static G4Class* GetInstance() 0054 // { 0055 // static G4Class theInstance; 0056 // if ( instance == nullptr ) instance = &theInstance; 0057 // return instance; 0058 // } 0059 // }; 0060 // This is transformed to the following to implement a thread-local 0061 // singleton: 0062 // class G4Class 0063 // { 0064 // private: 0065 // static G4ThreadLocal G4Class* instance; 0066 // G4Class() { ... } 0067 // public: 0068 // static G4Class* GetInstance() 0069 // { 0070 // if ( instance == nullptr ) instance = new G4Class; 0071 // return instance; 0072 // } 0073 // }; 0074 // Note that this class also has a memory leak. 0075 // 0076 // This class can be used as follows: 0077 // class G4Class 0078 // { 0079 // friend class G4ThreadLocalSingleton<G4Class>; 0080 // private: 0081 // G4Class() { ... } 0082 // public: 0083 // static G4Class* GetInstance() 0084 // { 0085 // static G4ThreadLocalSingleton<G4Class> instance; 0086 // return instance.Instance(); 0087 // } 0088 // }; 0089 // Each thread has its own instance of G4Class. 0090 // Deletion of G4Class instances is done at end of program. 0091 // Note the "friend" statement. 0092 0093 // Author: A.Dotti, 28 October 2013 0094 // -------------------------------------------------------------------- 0095 #ifndef G4TLSSINGLETON_HH 0096 #define G4TLSSINGLETON_HH 1 0097 0098 #include "G4AutoLock.hh" 0099 #include "G4Cache.hh" 0100 #include "G4Backtrace.hh" 0101 #include "G4Threading.hh" 0102 0103 #include <list> 0104 #include <vector> 0105 #include <functional> 0106 0107 // Forward declaration. See G4AutoDelete.hh 0108 // 0109 namespace G4AutoDelete 0110 { 0111 template <class T> 0112 void Register(T*); 0113 } 0114 0115 template <class T> 0116 class G4ThreadLocalSingleton; 0117 0118 // this explicit specialization holds all the callbacks 0119 // to explicitly invoke the auto-deletion 0120 template <> 0121 class G4ThreadLocalSingleton<void> 0122 { 0123 private: 0124 using fvector_t = std::vector<std::function<void()>>; 0125 0126 template <class T> 0127 friend class G4ThreadLocalSingleton; 0128 0129 static fvector_t& GetCallbacks(); 0130 static G4Mutex& GetMutex(); 0131 0132 public: 0133 static void Clear(); 0134 0135 template <typename FuncT> 0136 static typename fvector_t::iterator Insert(FuncT&& _func) 0137 { 0138 G4AutoLock _lk{ GetMutex() }; 0139 return GetCallbacks().emplace(GetCallbacks().end(), 0140 std::forward<FuncT>(_func)); 0141 } 0142 }; 0143 0144 template <class T> 0145 class G4ThreadLocalSingleton : private G4Cache<T*> 0146 { 0147 friend void G4AutoDelete::Register<T>(T*); 0148 0149 public: 0150 G4ThreadLocalSingleton(); 0151 // Creates thread-local singleton manager 0152 0153 ~G4ThreadLocalSingleton() override; 0154 0155 G4ThreadLocalSingleton(const G4ThreadLocalSingleton&) = delete; 0156 G4ThreadLocalSingleton(G4ThreadLocalSingleton&&) = default; 0157 0158 G4ThreadLocalSingleton& operator=(const G4ThreadLocalSingleton&) = delete; 0159 G4ThreadLocalSingleton& operator=(G4ThreadLocalSingleton&&) = default; 0160 0161 T* Instance() const; 0162 // Returns a pointer to a thread-private instance of T 0163 0164 private: 0165 void Register(T* i) const; 0166 0167 void Clear(); 0168 0169 mutable std::list<T*> instances; 0170 mutable G4Mutex listm; 0171 }; 0172 0173 //============================================================= 0174 // Inline methods implementation 0175 //============================================================= 0176 0177 template <class T> 0178 G4ThreadLocalSingleton<T>::G4ThreadLocalSingleton() 0179 : G4Cache<T*>() 0180 { 0181 G4MUTEXINIT(listm); 0182 G4Cache<T*>::Put(nullptr); 0183 // Uncomment below to find the origin of where instantiation happened 0184 /* 0185 auto bt = G4Backtrace::GetDemangled<4, 1>( 0186 [](const char* cstr) { return std::string{ cstr }; }); 0187 std::cout << "Backtrace to G4ThreadLocalSingleton<" 0188 << G4Demangle<T>().c_str() << ">:\n"; 0189 for(auto& itr : bt) 0190 { 0191 if(!itr.empty()) 0192 std::cout << "\t" << itr << "\n"; 0193 } 0194 */ 0195 G4ThreadLocalSingleton<void>::Insert([&]() { 0196 // printf("Deleting G4ThreadLocalSingletons for type %s ...\n", 0197 // G4Demangle<T>().c_str()); 0198 this->Clear(); 0199 }); 0200 } 0201 0202 template <class T> 0203 G4ThreadLocalSingleton<T>::~G4ThreadLocalSingleton() 0204 { 0205 Clear(); 0206 G4MUTEXDESTROY(listm); 0207 } 0208 0209 template <class T> 0210 T* G4ThreadLocalSingleton<T>::Instance() const 0211 { 0212 T* instance = G4Cache<T*>::Get(); 0213 if(instance == static_cast<T*>(0)) 0214 { 0215 instance = new T; 0216 G4Cache<T*>::Put(instance); 0217 Register(instance); 0218 } 0219 return instance; 0220 } 0221 0222 template <class T> 0223 void G4ThreadLocalSingleton<T>::Register(T* i) const 0224 { 0225 G4AutoLock l(&listm); 0226 instances.push_back(i); 0227 } 0228 0229 template <class T> 0230 void G4ThreadLocalSingleton<T>::Clear() 0231 { 0232 if(instances.empty()) 0233 return; 0234 G4AutoLock l(&listm); 0235 while(!instances.empty()) 0236 { 0237 T* thisinst = instances.front(); 0238 instances.pop_front(); 0239 delete thisinst; 0240 } 0241 } 0242 0243 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |