Geant4  10.02.p01
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 // $Id$
27 //
28 // ---------------------------------------------------------------
29 // GEANT 4 class header file
30 //
31 // Class Description:
32 // Helper classes for Geant4 Multi-Threaded.
33 // The classes defined in this header file provide a thread-private
34 // cache to store, in a class instance shared among threads,
35 // a thread-local variable V.
36 // These are templated classes on the to-be-stored object.
37 //
38 // Example:
39 // Let's assume an instance myObject of class G4Shared is sharead between
40 // threads. Still a data member of this class needs to be thread-private.
41 // A typical example of this being a "cache" for a local calculation.
42 // The helper here defined can be used to guarantee thread-safe operations
43 // on the thread-private object.
44 // Example:
45 // class G4Shared {
46 // G4double sharedData;
47 // G4Cache<G4double> threadPrivate;
48 // void foo() {
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 exists. 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 // cout<<aVect[0]<<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 // See testG4Cache unit test for details on usage
70 //
71 // History:
72 // 21 October 2013: A. Dotti - First implementation
73 
74 #ifndef G4CACHE_HH
75 #define G4CACHE_HH
76 
77 //Debug this code
78 //#define g4cdebug 1
79 
80 //Thread Local storage details are in this header file
81 #include "G4CacheDetails.hh"
82 
83 // A templated cache to store a thread-private data of type VALTYPE.
84 template<class VALTYPE>
85 class G4Cache {
86 public:
87  typedef VALTYPE value_type;
88  // The stored type
89 
90  G4Cache();
91  // Default constructor
92 
93  G4Cache(const value_type& v);
94  // Construct cache object with initial value
95 
96  virtual ~G4Cache();
97  // Default destructor
98 
99  inline value_type& Get() const;
100  // Gets reference to cached value of this threads
101 
102  inline void Put( const value_type& val ) const;
103  // Sets this thread cached value to val
104 
105  inline value_type Pop();
106  // Gets copy of cached value
107 
108  G4Cache(const G4Cache& rhs);
109  G4Cache& operator=(const G4Cache& rhs);
110 
111 protected:
112  const int& GetId() const { return id; }
113 private:
114  int id;
116  static G4Mutex gMutex;
117  static unsigned int instancesctr;
118  static unsigned int dstrctr;
119 
120  inline value_type& GetCache() const {
121  theCache.Initialize(id);
122  return theCache.GetCache(id);
123  }
124 
125 };
126 
127 
128 // A vector version of the cache. Implements vector interface.
129 // Can be used directly as a std::vector would be used.
130 template<class VALTYPE>
131 class G4VectorCache : public G4Cache< std::vector<VALTYPE> > {
132 public:
133  //Some useful defintions
134  typedef VALTYPE value_type;
135  typedef typename std::vector<value_type> vector_type;
136  typedef typename vector_type::size_type size_type;
137  typedef typename vector_type::iterator iterator;
138  typedef typename vector_type::const_iterator const_iterator;
139 
140  G4VectorCache();
141  // Default constructor
142 
143  G4VectorCache( G4int nElems );
144  // Creates a vector cache of nElems elements
145 
146  G4VectorCache( G4int nElems , value_type* vals );
147  // Creates a vector cache with elements from an array
148 
149  virtual ~G4VectorCache();
150  // Default destructor
151 
152  // Interface with funxtionalities of similar name of std::vector
153  inline void Push_back( const value_type& val );
154  inline value_type Pop_back();
155  inline value_type& operator[](const G4int& idx);
156  inline iterator Begin();
157  inline iterator End();
158  inline void Clear();
159  inline size_type Size() { return G4Cache<vector_type>::Get().size(); } //Needs to be here for a VC9 compilation problem
160 };
161 
162 
163 // a Map version of the cache. Implemetns std::map interface.
164 // Can be used directly as a std::map would be used.
165 // KEYTYPE being the key type and VALTYPE the value type.
166 #include <map>
167 template<class KEYTYPE, class VALTYPE>
168 class G4MapCache : public G4Cache<std::map<KEYTYPE,VALTYPE> > {
169 public:
170  //Some useful definitions
171  typedef KEYTYPE key_type;
172  typedef VALTYPE value_type;
173  typedef typename std::map<key_type,value_type> map_type;
174  typedef typename map_type::size_type size_type;
175  typedef typename map_type::iterator iterator;
176  typedef typename map_type::const_iterator const_iterator;
177 
178  virtual ~G4MapCache();
179  // Default destructor
180 
181  inline G4bool Has(const key_type& k );
182  // Returns true if map contains element corresponding to key k
183 
184  // Interface with functionalities of similar name of std::map
185  inline std::pair<iterator,G4bool> Insert( const key_type& k , const value_type& v );
186  inline iterator Begin();
187  inline iterator End();
188  inline iterator Find(const key_type& k );
189  inline value_type& Get(const key_type& k );
190  inline size_type Erase(const key_type& k );
191  inline value_type& operator[](const key_type& k);
192  inline size_type Size() { return G4Cache<map_type>::Get().size(); } //Needs to be here for a VC9 compilation problem
193 };
194 
195 
196 
197 //=============================================================
198 // Implementation details follow
199 //=============================================================
200 
201 
202 
203 #ifdef g4cdebug
204 #include <iostream>
205 #include <sstream>
206 using std::cout;
207 using std::endl;
208 #endif
209 
210 #include "G4AutoLock.hh"
211 
212 
213 //========= Implementation: G4Cache<V>
214 
215 template<class V>
217 {
218  G4AutoLock l(&gMutex);
219  id = instancesctr++;
220 #ifdef g4cdebug
221  cout<<"G4Cache id: "<<id<<endl;
222 #endif
223 }
224 
225 template<class V>
227 {
228  //Copy is special, we need to copy the content
229  //of the cache, not the cache object
230  if ( this == &rhs ) return;
231  G4AutoLock l(&gMutex);
232  id = instancesctr++;
233  //Force copy of cached data
234  V aCopy = rhs.GetCache();
235  Put( aCopy );
236 #ifdef g4cdebug
237  cout<<"Copy constructor with id: "<<id<<endl;
238 #endif
239 }
240 
241 template<class V>
243 {
244  if (this == &rhs) return *this;
245  //Force copy of cached data
246  V aCopy = rhs.GetCache();
247  Put(aCopy);
248 #ifdef g4cdebug
249  cout<<"Assignement operator with id: "<<id<<endl;
250 #endif
251  return *this;
252 }
253 
254 template<class V>
255 G4Cache<V>::G4Cache(const V& v)
256 {
257  G4AutoLock l(&gMutex);
258  id = instancesctr++;
259  Put(v);
260 #ifdef g4cdebug
261  cout<<"G4Cache id: "<<id<<" "<<endl;
262 #endif
263 }
264 
265 template<class V>
267 { //Move base calss
268 #ifdef g4cdebug
269  cout<<"~G4Cache id: "<<id<<" "<<endl;
270 #endif
271  G4AutoLock l(&gMutex);
272  ++dstrctr;
273  G4bool last = ( dstrctr == instancesctr );
274  theCache.Destroy(id,last);
275  if (last) {
276  instancesctr = 0;
277  dstrctr = 0;
278  }
279 }
280 
281 template<class V>
282 V& G4Cache<V>::Get() const
283 { return GetCache(); }
284 
285 template<class V>
286 void G4Cache<V>::Put( const V& val ) const
287 { GetCache() = val; }
288 
289 //Should here remove from cache element?
290 template<class V>
292 { return GetCache(); }
293 
294 template<class V>
295 unsigned int G4Cache<V>::instancesctr = 0;
296 
297 template<class V>
298 unsigned int G4Cache<V>::dstrctr = 0;
299 
300 template<class V>
302 
303 //========== Implementation: G4VectorCache<V>
304 template<class V>
306 { }
307 
308 template<class V>
310 #ifdef g4cdebug
311  cout<<"~G4VectorCache "<<G4Cache<G4VectorCache<V>::vector_type>::GetId()<<" with size: "<<Size()<<"->";
312  for ( size_type i = 0 ; i < Size() ; ++i )
313  cout<<operator[](i)<<",";
314  cout<<"<-"<<endl;
315 #endif
316 }
317 
318 template<class V>
321  cc.resize(nElems);
322 }
323 
324 template<class V>
325 G4VectorCache<V>::G4VectorCache(G4int nElems , V* vals ) {
326  vector_type& cc = G4Cache<vector_type>::Get();
327  cc.resize(nElems);
328  for ( G4int idx = 0 ; idx < nElems ; ++idx )
329  cc[idx]=vals[idx];
330 }
331 
332 template<class V>
333 void G4VectorCache<V>::Push_back( const V& val )
334 {
335  G4Cache<vector_type>::Get().push_back( val );
336 }
337 
338 template<class V>
340 {
342  value_type val = cc[cc.size()-1];
343  cc.pop_back();
344  return val;
345 }
346 
347 template<class V>
349 {
351  return cc[idx];
352 }
353 
354 template<class V>
356 {
357  return G4Cache<vector_type>::Get().begin();
358 }
359 
360 template<class V>
362 {
363  return G4Cache<vector_type>::Get().end();
364 }
365 
366 template<class V>
368 {
369  G4Cache<vector_type>::Get().clear();
370 }
371 
372 //template<class V>
373 //typename G4VectorCache<V>::size_type G4VectorCache<V>::Size()
374 //{
375 // return G4Cache<vector_type>::Get().size();
376 //}
377 
378 //======== Implementation: G4MapType<K,V>
379 template<class K, class V>
381 {
382 #ifdef g4cdebug
383  cout<<"~G4MacCache "<<G4Cache<map_type>::GetId()<<" with size: "<<Size()<<"->";
384  for ( iterator it = Begin() ; it != End() ; ++it )
385  cout<<it->first<<":"<<it->second<<",";
386  cout<<"<-"<<endl;
387 #endif
388 }
389 
390 template<class K, class V>
391 std::pair<typename G4MapCache<K,V>::iterator,G4bool> G4MapCache<K,V>::Insert(
392  const K& k,
393  const V& v
394  )
395 {
396  return G4Cache<map_type>::Get().insert( std::pair<key_type,value_type>(k,v) );
397 }
398 
399 //template<class K, class V>
400 //typename G4MapCache<K,V>::size_type G4MapCache<K,V>::Size()
401 //{
402 // return G4Cache<map_type>::Get().size();
403 //}
404 
405 template<class K, class V>
407 {
408  return G4Cache<map_type>::Get().begin();
409 }
410 template<class K, class V>
412 {
413  return G4Cache<map_type>::Get().end();
414 }
415 
416 template<class K, class V>
418 {
419  return G4Cache<map_type>::Get().find(k);
420 }
421 
422 template<class K, class V>
424 {
425  return ( Find(k) != End() );
426 }
427 
428 template<class K, class V>
429 V& G4MapCache<K,V>::Get(const K& k )
430 {
431  return Find(k)->second;
432 }
433 
434 template<class K, class V>
436 {
437  return G4Cache<map_type>::Get().erase(k);
438 }
439 
440 template<class K, class V>
442 {
443  return (G4Cache<map_type>::Get())[k];
444 }
445 
446 #endif
VALTYPE value_type
Definition: G4Cache.hh:87
G4CacheReference< value_type > theCache
Definition: G4Cache.hh:115
void Initialize(unsigned int id)
value_type & GetCache() const
Definition: G4Cache.hh:120
value_type Pop_back()
Definition: G4Cache.hh:339
iterator End()
Definition: G4Cache.hh:411
size_type Size()
Definition: G4Cache.hh:159
static unsigned int instancesctr
Definition: G4Cache.hh:117
iterator End()
Definition: G4Cache.hh:361
VALTYPE value_type
Definition: G4Cache.hh:134
value_type Pop()
Definition: G4Cache.hh:291
vector_type::const_iterator const_iterator
Definition: G4Cache.hh:138
value_type & Get() const
Definition: G4Cache.hh:282
size_type Size()
Definition: G4Cache.hh:192
virtual ~G4VectorCache()
Definition: G4Cache.hh:309
std::vector< value_type > vector_type
Definition: G4Cache.hh:135
int G4int
Definition: G4Types.hh:78
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:175
vector_type::iterator iterator
Definition: G4Cache.hh:137
virtual ~G4Cache()
Definition: G4Cache.hh:266
G4bool Has(const key_type &k)
Definition: G4Cache.hh:423
size_type Erase(const key_type &k)
Definition: G4Cache.hh:435
virtual ~G4MapCache()
Definition: G4Cache.hh:380
const int & GetId() const
Definition: G4Cache.hh:112
bool G4bool
Definition: G4Types.hh:79
void Clear()
Definition: G4Cache.hh:367
map_type::const_iterator const_iterator
Definition: G4Cache.hh:176
VALTYPE & GetCache(unsigned int id) const
value_type & operator[](const G4int &idx)
Definition: G4Cache.hh:348
void Push_back(const value_type &val)
Definition: G4Cache.hh:333
G4int G4Mutex
Definition: G4Threading.hh:173
iterator Find(const key_type &k)
Definition: G4Cache.hh:417
int id
Definition: G4Cache.hh:114
iterator Begin()
Definition: G4Cache.hh:355
map_type::iterator iterator
Definition: G4Cache.hh:175
G4Cache & operator=(const G4Cache &rhs)
Definition: G4Cache.hh:242
map_type::size_type size_type
Definition: G4Cache.hh:174
KEYTYPE key_type
Definition: G4Cache.hh:171
iterator Begin()
Definition: G4Cache.hh:406
std::map< key_type, value_type > map_type
Definition: G4Cache.hh:173
G4Cache()
Definition: G4Cache.hh:216
value_type & operator[](const key_type &k)
Definition: G4Cache.hh:441
static unsigned int dstrctr
Definition: G4Cache.hh:118
void Put(const value_type &val) const
Definition: G4Cache.hh:286
std::pair< iterator, G4bool > Insert(const key_type &k, const value_type &v)
Definition: G4Cache.hh:391
VALTYPE value_type
Definition: G4Cache.hh:172
static G4Mutex gMutex
Definition: G4Cache.hh:116
vector_type::size_type size_type
Definition: G4Cache.hh:136