Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4ThreadLocalSingleton.hh
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4ThreadLocalSingleton
27//
28// Class description:
29//
30// This class implements a thread-private "singleton". Being thread
31// private the singleton is not a singleton in the term, but a different
32// instance exists for each thread.
33// This class is a wrapper around the real object that we need to
34// make singleton.
35//
36// Limitation:
37// The object that is made thread-private singleton should not
38// contain any thread-local data member. Note that in general,
39// if an object is to be thread-private it is unnecessary to mark
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 in Geant4 (sequential):
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 = &theInstance;
57// return instance;
58// }
59// };
60// This is transformed to the following to implement a thread-local
61// singleton:
62// class G4Class
63// {
64// private:
65// static G4ThreadLocal G4Class* instance;
66// G4Class() { ... }
67// public:
68// static G4Class* GetInstance()
69// {
70// if ( instance == nullptr ) instance = new G4Class;
71// return instance;
72// }
73// };
74// Note that this class also has a memory leak.
75//
76// This class can be used as follows:
77// class G4Class
78// {
79// friend class G4ThreadLocalSingleton<G4Class>;
80// private:
81// G4Class() { ... }
82// public:
83// static G4Class* GetInstance()
84// {
85// static G4ThreadLocalSingleton<G4Class> instance;
86// return instance.Instance();
87// }
88// };
89// Each thread has its own instance of G4Class.
90// Deletion of G4Class instances is done at end of program.
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//
109namespace G4AutoDelete
110{
111 template <class T>
112 void Register(T*);
113}
114
115template <class T>
117
118// this explicit specialization holds all the callbacks
119// to explicitly invoke the auto-deletion
120template <>
122{
123 private:
124 using fvector_t = std::vector<std::function<void()>>;
125
126 template <class T>
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(FuncT&& _func)
137 {
138 G4AutoLock _lk{ GetMutex() };
139 return GetCallbacks().emplace(GetCallbacks().end(),
140 std::forward<FuncT>(_func));
141 }
142};
143
144template <class T>
146{
147 friend void G4AutoDelete::Register<T>(T*);
148
149 public:
151 // Creates thread-local singleton manager
152
153 ~G4ThreadLocalSingleton() override;
154
157
160
161 T* Instance() const;
162 // Returns a pointer to a thread-private instance of T
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
177template <class T>
179 : G4Cache<T*>()
180{
181 G4MUTEXINIT(listm);
182 G4Cache<T*>::Put(nullptr);
183 // Uncomment below to find the origin of where instantiation happened
184 /*
185 auto bt = G4Backtrace::GetDemangled<4, 1>(
186 [](const char* cstr) { return std::string{ cstr }; });
187 std::cout << "Backtrace to G4ThreadLocalSingleton<"
188 << G4Demangle<T>().c_str() << ">:\n";
189 for(auto& itr : bt)
190 {
191 if(!itr.empty())
192 std::cout << "\t" << itr << "\n";
193 }
194 */
196 // printf("Deleting G4ThreadLocalSingletons for type %s ...\n",
197 // G4Demangle<T>().c_str());
198 this->Clear();
199 });
200}
201
202template <class T>
204{
205 Clear();
206 G4MUTEXDESTROY(listm);
207}
208
209template <class T>
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
222template <class T>
224{
225 G4AutoLock l(&listm);
226 instances.push_back(i);
227}
228
229template <class T>
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
#define G4MUTEXDESTROY(mutex)
Definition: G4Threading.hh:90
std::mutex G4Mutex
Definition: G4Threading.hh:81
#define G4MUTEXINIT(mutex)
Definition: G4Threading.hh:87
value_type & Get() const
Definition: G4Cache.hh:315
void Put(const value_type &val) const
Definition: G4Cache.hh:321
static fvector_t::iterator Insert(FuncT &&_func)
G4ThreadLocalSingleton & operator=(G4ThreadLocalSingleton &&)=default
G4ThreadLocalSingleton(G4ThreadLocalSingleton &&)=default
G4ThreadLocalSingleton(const G4ThreadLocalSingleton &)=delete
friend void G4AutoDelete::Register(T *)
G4ThreadLocalSingleton & operator=(const G4ThreadLocalSingleton &)=delete
void Register(T *inst)
Definition: G4AutoDelete.hh:65