![]() |
|
|||
File indexing completed on 2025-09-17 08:59:32
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 "G4Threading.hh" 0101 0102 #include <list> 0103 #include <vector> 0104 #include <functional> 0105 0106 // Forward declaration. See G4AutoDelete.hh 0107 // 0108 namespace G4AutoDelete 0109 { 0110 template <class T> 0111 void Register(T*); 0112 } 0113 0114 template <class T> 0115 class G4ThreadLocalSingleton; 0116 0117 // this explicit specialization holds all the callbacks 0118 // to explicitly invoke the auto-deletion 0119 template <> 0120 class G4ThreadLocalSingleton<void> 0121 { 0122 private: 0123 using fvector_t = std::vector<std::function<void()>>; 0124 0125 template <class T> 0126 friend class G4ThreadLocalSingleton; 0127 0128 static fvector_t& GetCallbacks(); 0129 static G4Mutex& GetMutex(); 0130 0131 public: 0132 static void Clear(); 0133 0134 template <typename FuncT> 0135 static typename fvector_t::iterator Insert(FuncT&& _func) 0136 { 0137 G4AutoLock _lk{ GetMutex() }; 0138 return GetCallbacks().emplace(GetCallbacks().end(), 0139 std::forward<FuncT>(_func)); 0140 } 0141 }; 0142 0143 template <class T> 0144 class G4ThreadLocalSingleton : private G4Cache<T*> 0145 { 0146 friend void G4AutoDelete::Register<T>(T*); 0147 0148 public: 0149 G4ThreadLocalSingleton(); 0150 // Creates thread-local singleton manager 0151 0152 ~G4ThreadLocalSingleton() override; 0153 0154 G4ThreadLocalSingleton(const G4ThreadLocalSingleton&) = delete; 0155 G4ThreadLocalSingleton(G4ThreadLocalSingleton&&) = default; 0156 0157 G4ThreadLocalSingleton& operator=(const G4ThreadLocalSingleton&) = delete; 0158 G4ThreadLocalSingleton& operator=(G4ThreadLocalSingleton&&) = default; 0159 0160 T* Instance() const; 0161 // Returns a pointer to a thread-private instance of T 0162 0163 private: 0164 void Register(T* i) const; 0165 0166 void Clear(); 0167 0168 mutable std::list<T*> instances; 0169 mutable G4Mutex listm; 0170 }; 0171 0172 //============================================================= 0173 // Inline methods implementation 0174 //============================================================= 0175 0176 template <class T> 0177 G4ThreadLocalSingleton<T>::G4ThreadLocalSingleton() 0178 : G4Cache<T*>() 0179 { 0180 G4MUTEXINIT(listm); 0181 G4Cache<T*>::Put(nullptr); 0182 G4ThreadLocalSingleton<void>::Insert([&]() { 0183 this->Clear(); 0184 }); 0185 } 0186 0187 template <class T> 0188 G4ThreadLocalSingleton<T>::~G4ThreadLocalSingleton() 0189 { 0190 Clear(); 0191 G4MUTEXDESTROY(listm); 0192 } 0193 0194 template <class T> 0195 T* G4ThreadLocalSingleton<T>::Instance() const 0196 { 0197 T* instance = G4Cache<T*>::Get(); 0198 if(instance == static_cast<T*>(0)) 0199 { 0200 instance = new T; 0201 G4Cache<T*>::Put(instance); 0202 Register(instance); 0203 } 0204 return instance; 0205 } 0206 0207 template <class T> 0208 void G4ThreadLocalSingleton<T>::Register(T* i) const 0209 { 0210 G4AutoLock l(&listm); 0211 instances.push_back(i); 0212 } 0213 0214 template <class T> 0215 void G4ThreadLocalSingleton<T>::Clear() 0216 { 0217 if(instances.empty()) 0218 return; 0219 G4AutoLock l(&listm); 0220 while(!instances.empty()) 0221 { 0222 T* thisinst = instances.front(); 0223 instances.pop_front(); 0224 delete thisinst; 0225 } 0226 } 0227 0228 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |