Geant4-11
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 typedef VALTYPE value_type;
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:
121 static std::atomic<unsigned int> instancesctr;
122 static std::atomic<unsigned int> dstrctr;
123
124 inline value_type& GetCache() const
125 {
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 typedef VALTYPE value_type;
141 typedef typename std::vector<value_type> vector_type;
142 typedef typename vector_type::size_type size_type;
143 typedef typename vector_type::iterator iterator;
144 typedef typename vector_type::const_iterator 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 typedef KEYTYPE key_type;
181 typedef VALTYPE value_type;
182 typedef typename std::map<key_type, value_type> map_type;
183 typedef typename map_type::size_type size_type;
184 typedef typename map_type::iterator iterator;
185 typedef typename map_type::const_iterator 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{}
344
345template <class V>
347{
348#ifdef g4cdebug
349 std::cout << "~G4VectorCache "
351 << " with size: " << Size() << "->";
352 for(size_type i = 0; i < Size(); ++i)
353 std::cout << operator[](i) << ",";
354 std::cout << "<-" << std::endl;
355#endif
356}
357
358template <class V>
360{
362 cc.resize(nElems);
363}
364
365template <class V>
367{
368 vector_type& cc = G4Cache<vector_type>::Get();
369 cc.resize(nElems);
370 for(G4int idx = 0; idx < nElems; ++idx)
371 cc[idx] = vals[idx];
372}
373
374template <class V>
376{
377 G4Cache<vector_type>::Get().push_back(val);
378}
379
380template <class V>
382{
384 value_type val = cc[cc.size() - 1];
385 cc.pop_back();
386 return val;
387}
388
389template <class V>
391{
393 return cc[idx];
394}
395
396template <class V>
398{
399 return G4Cache<vector_type>::Get().begin();
400}
401
402template <class V>
404{
405 return G4Cache<vector_type>::Get().end();
406}
407
408template <class V>
410{
412}
413
414// template<class V>
415// typename G4VectorCache<V>::size_type G4VectorCache<V>::Size()
416//{
417// return G4Cache<vector_type>::Get().size();
418//}
419
420//======== Implementation: G4MapType<K,V> ===========================
421
422template <class K, class V>
424{
425#ifdef g4cdebug
426 std::cout << "~G4MacCache " << G4Cache<map_type>::GetId()
427 << " with size: " << Size() << "->";
428 for(iterator it = Begin(); it != End(); ++it)
429 std::cout << it->first << ":" << it->second << ",";
430 std::cout << "<-" << std::endl;
431#endif
432}
433
434template <class K, class V>
435std::pair<typename G4MapCache<K, V>::iterator, G4bool> G4MapCache<K, V>::Insert(
436 const K& k, const V& v)
437{
438 return G4Cache<map_type>::Get().insert(std::pair<key_type, value_type>(k, v));
439}
440
441// template<class K, class V>
442// typename G4MapCache<K,V>::size_type G4MapCache<K,V>::Size()
443//{
444// return G4Cache<map_type>::Get().size();
445//}
446
447template <class K, class V>
449{
450 return G4Cache<map_type>::Get().begin();
451}
452template <class K, class V>
454{
455 return G4Cache<map_type>::Get().end();
456}
457
458template <class K, class V>
460{
461 return G4Cache<map_type>::Get().find(k);
462}
463
464template <class K, class V>
466{
467 return (Find(k) != End());
468}
469
470template <class K, class V>
472{
473 return Find(k)->second;
474}
475
476template <class K, class V>
478{
479 return G4Cache<map_type>::Get().erase(k);
480}
481
482template <class K, class V>
484{
485 return (G4Cache<map_type>::Get())[k];
486}
487
488#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)
value_type & Get() const
Definition: G4Cache.hh:315
G4CacheReference< value_type > theCache
Definition: G4Cache.hh:120
const G4int & GetId() const
Definition: G4Cache.hh:116
value_type Pop()
Definition: G4Cache.hh:328
G4int id
Definition: G4Cache.hh:119
VALTYPE value_type
Definition: G4Cache.hh:91
virtual ~G4Cache()
Definition: G4Cache.hh:270
G4Cache(const G4Cache &rhs)
value_type & GetCache() const
Definition: G4Cache.hh:124
void Put(const value_type &val) const
Definition: G4Cache.hh:321
static std::atomic< unsigned int > instancesctr
Definition: G4Cache.hh:121
G4Cache(const value_type &v)
G4Cache()
Definition: G4Cache.hh:210
static std::atomic< unsigned int > dstrctr
Definition: G4Cache.hh:122
G4Cache & operator=(const G4Cache &rhs)
Definition: G4Cache.hh:241
map_type::iterator iterator
Definition: G4Cache.hh:184
iterator Begin()
Definition: G4Cache.hh:448
std::map< key_type, value_type > map_type
Definition: G4Cache.hh:182
KEYTYPE key_type
Definition: G4Cache.hh:180
virtual ~G4MapCache()
Definition: G4Cache.hh:423
value_type & Get(const key_type &k)
Definition: G4Cache.hh:471
std::pair< iterator, G4bool > Insert(const key_type &k, const value_type &v)
Definition: G4Cache.hh:435
iterator Find(const key_type &k)
Definition: G4Cache.hh:459
size_type Erase(const key_type &k)
Definition: G4Cache.hh:477
iterator End()
Definition: G4Cache.hh:453
G4bool Has(const key_type &k)
Definition: G4Cache.hh:465
value_type & operator[](const key_type &k)
Definition: G4Cache.hh:483
size_type Size()
Definition: G4Cache.hh:203
map_type::size_type size_type
Definition: G4Cache.hh:183
VALTYPE value_type
Definition: G4Cache.hh:181
map_type::const_iterator const_iterator
Definition: G4Cache.hh:185
value_type & operator[](const G4int &idx)
Definition: G4Cache.hh:390
G4VectorCache(G4int nElems, value_type *vals)
size_type Size()
Definition: G4Cache.hh:166
value_type Pop_back()
Definition: G4Cache.hh:381
vector_type::iterator iterator
Definition: G4Cache.hh:143
G4VectorCache(G4int nElems)
Definition: G4Cache.hh:359
virtual ~G4VectorCache()
Definition: G4Cache.hh:346
vector_type::const_iterator const_iterator
Definition: G4Cache.hh:144
std::vector< value_type > vector_type
Definition: G4Cache.hh:141
void Clear()
Definition: G4Cache.hh:409
void Push_back(const value_type &val)
Definition: G4Cache.hh:375
iterator Begin()
Definition: G4Cache.hh:397
VALTYPE value_type
Definition: G4Cache.hh:140
iterator End()
Definition: G4Cache.hh:403
vector_type::size_type size_type
Definition: G4Cache.hh:142
const char * name(G4int ptype)