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
G4Cache.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// G4Cache
27//
28// Class Description:
29//
30// Helper classes for Geant4 Multi-Threaded.
31// The classes defined in this header file provide a thread-private
32// cache to store a thread-local variable V in a class instance
33// shared among threads.
34// These are templated classes on the to-be-stored object.
35//
36// Example:
37// Let's assume an instance myObject of class G4Shared is sharead between
38// threads. Still a data member of this class needs to be thread-private.
39// A typical example of this being a "cache" for a local calculation.
40// The helper defined here can be used to guarantee thread-safe operations
41// on the thread-private object.
42// Example:
43// class G4Shared
44// {
45// G4double sharedData;
46// G4Cache<G4double> threadPrivate;
47// void foo()
48// {
49// G4double priv = threadPrivate.Get();
50// if ( priv < 10 ) priv += sharedData;
51// threadPrivate.Put( priv );
52// }
53// }
54//
55// Two variants of the base G4Cache exist. The first one being
56// G4VectorCache similar to std::vector.
57// Example:
58// G4VectorCache<G4double> aVect;
59// aVect.Push_back( 3.2 );
60// aVect.Push_back( 4.1 );
61// std::cout << aVect[0] << std::endl;
62// The second one being:
63// G4MapCache, similar to std::map.
64// Example:
65// G4MapCache<G4int, G4double> aMap;
66// aMap[320]=1.234;
67//
68// See classes definition for details.
69
70// Author: A.Dotti, 21 October 2013 - First implementation
71// --------------------------------------------------------------------
72#ifndef G4CACHE_HH
73#define G4CACHE_HH
74
75// Debug this code
76// #define g4cdebug 1
77
78#include <atomic>
79#include <map>
80#include <system_error>
81
82#include "G4AutoLock.hh"
83#include "G4CacheDetails.hh" // Thread Local storage details are here
84
85// A templated cache to store a thread-private data of type VALTYPE.
86//
87template <class VALTYPE>
89{
90 public:
91 using value_type = VALTYPE;
92 // The stored type
93
95 // Default constructor
96
98 // Construct cache object with initial value
99
100 virtual ~G4Cache();
101 // Default destructor
102
103 inline value_type& Get() const;
104 // Gets reference to cached value of this threads
105
106 inline void Put(const value_type& val) const;
107 // Sets this thread cached value to val
108
109 inline value_type Pop();
110 // Gets copy of cached value
111
112 G4Cache(const G4Cache& rhs);
114
115 protected:
116 const G4int& GetId() const { return id; }
117
118 private:
119 G4int id;
120 mutable G4CacheReference<value_type> theCache;
121 static std::atomic<unsigned int> instancesctr;
122 static std::atomic<unsigned int> dstrctr;
123
124 inline value_type& GetCache() const
125 {
126 theCache.Initialize(id);
127 return theCache.GetCache(id);
128 }
129};
130
131// A vector version of the cache. Implements vector interface.
132// Can be used directly as a std::vector would be used.
133//
134template <class VALTYPE>
135class G4VectorCache : public G4Cache<std::vector<VALTYPE>>
136{
137 public:
138 // Some useful definitions
139 //
140 using value_type = VALTYPE;
141 using vector_type = typename std::vector<value_type>;
142 using size_type = typename vector_type::size_type;
143 using iterator = typename vector_type::iterator;
144 using const_iterator = typename vector_type::const_iterator;
145
147 // Default constructor
148
150 // Creates a vector cache of nElems elements
151
153 // Creates a vector cache with elements from an array
154
155 virtual ~G4VectorCache();
156 // Default destructor
157
158 // Interface with functionalities of similar name of std::vector
159 //
160 inline void Push_back(const value_type& val);
162 inline value_type& operator[](const G4int& idx);
163 inline iterator Begin();
164 inline iterator End();
165 inline void Clear();
166 inline size_type Size() { return G4Cache<vector_type>::Get().size(); }
167 // Needs to be here for a VC9 compilation problem
168};
169
170// a Map version of the cache. Implements std::map interface.
171// Can be used directly as a std::map would be used.
172// KEYTYPE being the key type and VALTYPE the value type.
173//
174template <class KEYTYPE, class VALTYPE>
175class G4MapCache : public G4Cache<std::map<KEYTYPE, VALTYPE>>
176{
177 public:
178 // Some useful definitions
179 //
180 using key_type = KEYTYPE;
181 using value_type = VALTYPE;
182 using map_type = typename std::map<key_type, value_type>;
183 using size_type = typename map_type::size_type;
184 using iterator = typename map_type::iterator;
185 using const_iterator = typename map_type::const_iterator;
186
187 virtual ~G4MapCache();
188 // Default destructor
189
190 inline G4bool Has(const key_type& k);
191 // Returns true if map contains element corresponding to key k
192
193 // Interface with functionalities of similar name of std::map
194 //
195 inline std::pair<iterator, G4bool> Insert(const key_type& k,
196 const value_type& v);
197 inline iterator Begin();
198 inline iterator End();
199 inline iterator Find(const key_type& k);
200 inline value_type& Get(const key_type& k);
201 inline size_type Erase(const key_type& k);
202 inline value_type& operator[](const key_type& k);
203 inline size_type Size() { return G4Cache<map_type>::Get().size(); }
204 // Needs to be here for a VC9 compilation problem
205};
206
207//========= Implementation: G4Cache<V> ====================================
208
209template <class V>
211{
213 id = instancesctr++;
214#ifdef g4cdebug
215 std::cout << "G4Cache id: " << id << std::endl;
216#endif
217}
218
219template <class V>
221{
222 // Copy is special, we need to copy the content
223 // of the cache, not the cache object
224
225 if(this == &rhs)
226 return;
228 id = instancesctr++;
229
230 // Force copy of cached data
231 //
232 V aCopy = rhs.GetCache();
233 Put(aCopy);
234
235#ifdef g4cdebug
236 std::cout << "Copy constructor with id: " << id << std::endl;
237#endif
238}
239
240template <class V>
242{
243 if(this == &rhs)
244 return *this;
245
246 // Force copy of cached data
247 //
248 V aCopy = rhs.GetCache();
249 Put(aCopy);
250
251#ifdef g4cdebug
252 std::cout << "Assignement operator with id: " << id << std::endl;
253#endif
254 return *this;
255}
256
257template <class V>
258G4Cache<V>::G4Cache(const V& v)
259{
261 id = instancesctr++;
262 Put(v);
263
264#ifdef g4cdebug
265 std::cout << "G4Cache id: " << id << std::endl;
266#endif
267}
268
269template <class V>
271{
272#ifdef g4cdebug
273 std::cout << "~G4Cache id: " << id << std::endl;
274#endif
275 // don't automatically lock --> wait until we can catch an error
276 // without scoping the G4AutoLock
277 //
278 G4AutoLock l(G4TypeMutex<G4Cache<V>>(), std::defer_lock);
279
280 // sometimes the mutex is unavailable in destructors so
281 // try to lock the associated mutex, but catch if it fails
282 try
283 {
284 // a system_error in lock means that the mutex is unavailable
285 // we want to throw the error that comes from locking an unavailable
286 // mutex so that we know there is a memory leak
287 // if the mutex is valid, this will hold until the other thread finishes
288 //
289 l.lock();
290 } catch(std::system_error& e)
291 {
292 // the error that comes from locking an unavailable mutex
293#ifdef G4VERBOSE
294 G4cout << "Non-critical error: mutex lock failure in ~G4Cache<"
295 << typeid(V).name() << ">. " << G4endl
296 << "If the RunManagerKernel has been deleted, it failed to "
297 << "delete an allocated resource" << G4endl
298 << "and this destructor is being called after the statics "
299 << "were destroyed." << G4endl;
300 G4cout << "Exception: [code: " << e.code() << "] caught: " << e.what()
301 << G4endl;
302#endif
303 }
304 ++dstrctr;
305 G4bool last = (dstrctr == instancesctr);
306 theCache.Destroy(id, last);
307 if(last)
308 {
309 instancesctr.store(0);
310 dstrctr.store(0);
311 }
312}
313
314template <class V>
316{
317 return GetCache();
318}
319
320template <class V>
321void G4Cache<V>::Put(const V& val) const
322{
323 GetCache() = val;
324}
325
326// Should here remove from cache element?
327template <class V>
329{
330 return GetCache();
331}
332
333template <class V>
334std::atomic<unsigned int> G4Cache<V>::instancesctr(0);
335
336template <class V>
337std::atomic<unsigned int> G4Cache<V>::dstrctr(0);
338
339//========== Implementation: G4VectorCache<V> ===========================
340
341template <class V>
343
344template <class V>
346{
347#ifdef g4cdebug
348 std::cout << "~G4VectorCache "
350 << " with size: " << Size() << "->";
351 for(size_type i = 0; i < Size(); ++i)
352 std::cout << operator[](i) << ",";
353 std::cout << "<-" << std::endl;
354#endif
355}
356
357template <class V>
359{
361 cc.resize(nElems);
362}
363
364template <class V>
366{
367 vector_type& cc = G4Cache<vector_type>::Get();
368 cc.resize(nElems);
369 for(G4int idx = 0; idx < nElems; ++idx)
370 cc[idx] = vals[idx];
371}
372
373template <class V>
375{
376 G4Cache<vector_type>::Get().push_back(val);
377}
378
379template <class V>
381{
383 value_type val = cc[cc.size() - 1];
384 cc.pop_back();
385 return val;
386}
387
388template <class V>
390{
392 return cc[idx];
393}
394
395template <class V>
397{
398 return G4Cache<vector_type>::Get().begin();
399}
400
401template <class V>
403{
404 return G4Cache<vector_type>::Get().end();
405}
406
407template <class V>
409{
411}
412
413// template<class V>
414// typename G4VectorCache<V>::size_type G4VectorCache<V>::Size()
415//{
416// return G4Cache<vector_type>::Get().size();
417//}
418
419//======== Implementation: G4MapType<K,V> ===========================
420
421template <class K, class V>
423{
424#ifdef g4cdebug
425 std::cout << "~G4MacCache " << G4Cache<map_type>::GetId()
426 << " with size: " << Size() << "->";
427 for(iterator it = Begin(); it != End(); ++it)
428 std::cout << it->first << ":" << it->second << ",";
429 std::cout << "<-" << std::endl;
430#endif
431}
432
433template <class K, class V>
434std::pair<typename G4MapCache<K, V>::iterator, G4bool> G4MapCache<K, V>::Insert(
435 const K& k, const V& v)
436{
437 return G4Cache<map_type>::Get().insert(std::pair<key_type, value_type>(k, v));
438}
439
440// template<class K, class V>
441// typename G4MapCache<K,V>::size_type G4MapCache<K,V>::Size()
442//{
443// return G4Cache<map_type>::Get().size();
444//}
445
446template <class K, class V>
448{
449 return G4Cache<map_type>::Get().begin();
450}
451template <class K, class V>
453{
454 return G4Cache<map_type>::Get().end();
455}
456
457template <class K, class V>
459{
460 return G4Cache<map_type>::Get().find(k);
461}
462
463template <class K, class V>
465{
466 return (Find(k) != End());
467}
468
469template <class K, class V>
471{
472 return Find(k)->second;
473}
474
475template <class K, class V>
477{
478 return G4Cache<map_type>::Get().erase(k);
479}
480
481template <class K, class V>
483{
484 return (G4Cache<map_type>::Get())[k];
485}
486
487#endif
G4Mutex & G4TypeMutex(const unsigned int &_n=0)
Definition: G4Threading.hh:124
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
VALTYPE & GetCache(unsigned int id) const
void Initialize(unsigned int id)
void Destroy(unsigned int id, G4bool last)
value_type & Get() const
Definition: G4Cache.hh:315
const G4int & GetId() const
Definition: G4Cache.hh:116
VALTYPE value_type
Definition: G4Cache.hh:91
value_type Pop()
Definition: G4Cache.hh:328
virtual ~G4Cache()
Definition: G4Cache.hh:270
G4Cache(const G4Cache &rhs)
void Put(const value_type &val) const
Definition: G4Cache.hh:321
G4Cache(const value_type &v)
G4Cache()
Definition: G4Cache.hh:210
G4Cache & operator=(const G4Cache &rhs)
Definition: G4Cache.hh:241
typename map_type::iterator iterator
Definition: G4Cache.hh:184
typename map_type::size_type size_type
Definition: G4Cache.hh:183
iterator Begin()
Definition: G4Cache.hh:447
virtual ~G4MapCache()
Definition: G4Cache.hh:422
value_type & Get(const key_type &k)
Definition: G4Cache.hh:470
std::pair< iterator, G4bool > Insert(const key_type &k, const value_type &v)
Definition: G4Cache.hh:434
iterator Find(const key_type &k)
Definition: G4Cache.hh:458
size_type Erase(const key_type &k)
Definition: G4Cache.hh:476
iterator End()
Definition: G4Cache.hh:452
G4bool Has(const key_type &k)
Definition: G4Cache.hh:464
value_type & operator[](const key_type &k)
Definition: G4Cache.hh:482
typename std::map< key_type, value_type > map_type
Definition: G4Cache.hh:182
size_type Size()
Definition: G4Cache.hh:203
KEYTYPE key_type
Definition: G4Cache.hh:180
VALTYPE value_type
Definition: G4Cache.hh:181
typename map_type::const_iterator const_iterator
Definition: G4Cache.hh:185
value_type & operator[](const G4int &idx)
Definition: G4Cache.hh:389
typename vector_type::size_type size_type
Definition: G4Cache.hh:142
G4VectorCache(G4int nElems, value_type *vals)
size_type Size()
Definition: G4Cache.hh:166
typename vector_type::const_iterator const_iterator
Definition: G4Cache.hh:144
typename vector_type::iterator iterator
Definition: G4Cache.hh:143
typename std::vector< value_type > vector_type
Definition: G4Cache.hh:141
value_type Pop_back()
Definition: G4Cache.hh:380
G4VectorCache(G4int nElems)
Definition: G4Cache.hh:358
virtual ~G4VectorCache()
Definition: G4Cache.hh:345
void Clear()
Definition: G4Cache.hh:408
void Push_back(const value_type &val)
Definition: G4Cache.hh:374
VALTYPE value_type
Definition: G4Cache.hh:140
iterator Begin()
Definition: G4Cache.hh:396
iterator End()
Definition: G4Cache.hh:402