Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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 "G4Threading.hh"
101
102#include <list>
103#include <vector>
104#include <functional>
105
106// Forward declaration. See G4AutoDelete.hh
107//
108namespace G4AutoDelete
109{
110 template <class T>
111 void Register(T*);
112}
113
114template <class T>
116
117// this explicit specialization holds all the callbacks
118// to explicitly invoke the auto-deletion
119template <>
121{
122 private:
123 using fvector_t = std::vector<std::function<void()>>;
124
125 template <class T>
127
128 static fvector_t& GetCallbacks();
129 static G4Mutex& GetMutex();
130
131 public:
132 static void Clear();
133
134 template <typename FuncT>
135 static typename fvector_t::iterator Insert(FuncT&& _func)
136 {
137 G4AutoLock _lk{ GetMutex() };
138 return GetCallbacks().emplace(GetCallbacks().end(),
139 std::forward<FuncT>(_func));
140 }
141};
142
143template <class T>
145{
147
148 public:
150 // Creates thread-local singleton manager
151
153
156
159
160 T* Instance() const;
161 // Returns a pointer to a thread-private instance of T
162
163 private:
164 void Register(T* i) const;
165
166 void Clear();
167
168 mutable std::list<T*> instances;
169 mutable G4Mutex listm;
170};
171
172//=============================================================
173// Inline methods implementation
174//=============================================================
175
176template <class T>
178 : G4Cache<T*>()
179{
180 G4MUTEXINIT(listm);
181 G4Cache<T*>::Put(nullptr);
183 this->Clear();
184 });
185}
186
187template <class T>
193
194template <class T>
196{
198 if(instance == static_cast<T*>(0))
199 {
200 instance = new T;
203 }
204 return instance;
205}
206
207template <class T>
209{
210 G4AutoLock l(&listm);
211 instances.push_back(i);
212}
213
214template <class T>
215void G4ThreadLocalSingleton<T>::Clear()
216{
217 if(instances.empty())
218 return;
219 G4AutoLock l(&listm);
220 while(!instances.empty())
221 {
222 T* thisinst = instances.front();
223 instances.pop_front();
224 delete thisinst;
225 }
226}
227
228#endif
G4TemplateAutoLock< G4Mutex > G4AutoLock
G4TemplateRNGHelper< G4long > * G4TemplateRNGHelper< G4long >::instance
#define G4MUTEXDESTROY(mutex)
std::mutex G4Mutex
#define G4MUTEXINIT(mutex)
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)