File indexing completed on 2025-01-18 09:57:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 #ifndef G4CACHE_HH
0073 #define G4CACHE_HH
0074
0075
0076
0077
0078 #include <atomic>
0079 #include <map>
0080 #include <system_error>
0081
0082 #include "G4AutoLock.hh"
0083 #include "G4CacheDetails.hh" // Thread Local storage details are here
0084
0085
0086
0087 template <class VALTYPE>
0088 class G4Cache
0089 {
0090 public:
0091 using value_type = VALTYPE;
0092
0093
0094 G4Cache();
0095
0096
0097 G4Cache(const value_type& v);
0098
0099
0100 virtual ~G4Cache();
0101
0102
0103 inline value_type& Get() const;
0104
0105
0106 inline void Put(const value_type& val) const;
0107
0108
0109 inline value_type Pop();
0110
0111
0112 G4Cache(const G4Cache& rhs);
0113 G4Cache& operator=(const G4Cache& rhs);
0114
0115 protected:
0116 const G4int& GetId() const { return id; }
0117
0118 private:
0119 G4int id;
0120 mutable G4CacheReference<value_type> theCache;
0121 static std::atomic<unsigned int> instancesctr;
0122 static std::atomic<unsigned int> dstrctr;
0123
0124 inline value_type& GetCache() const
0125 {
0126 theCache.Initialize(id);
0127 return theCache.GetCache(id);
0128 }
0129 };
0130
0131
0132
0133
0134 template <class VALTYPE>
0135 class G4VectorCache : public G4Cache<std::vector<VALTYPE>>
0136 {
0137 public:
0138
0139
0140 using value_type = VALTYPE;
0141 using vector_type = typename std::vector<value_type>;
0142 using size_type = typename vector_type::size_type;
0143 using iterator = typename vector_type::iterator;
0144 using const_iterator = typename vector_type::const_iterator;
0145
0146 G4VectorCache();
0147
0148
0149 G4VectorCache(G4int nElems);
0150
0151
0152 G4VectorCache(G4int nElems, value_type* vals);
0153
0154
0155 virtual ~G4VectorCache();
0156
0157
0158
0159
0160 inline void Push_back(const value_type& val);
0161 inline value_type Pop_back();
0162 inline value_type& operator[](const G4int& idx);
0163 inline iterator Begin();
0164 inline iterator End();
0165 inline void Clear();
0166 inline size_type Size() { return G4Cache<vector_type>::Get().size(); }
0167
0168 };
0169
0170
0171
0172
0173
0174 template <class KEYTYPE, class VALTYPE>
0175 class G4MapCache : public G4Cache<std::map<KEYTYPE, VALTYPE>>
0176 {
0177 public:
0178
0179
0180 using key_type = KEYTYPE;
0181 using value_type = VALTYPE;
0182 using map_type = typename std::map<key_type, value_type>;
0183 using size_type = typename map_type::size_type;
0184 using iterator = typename map_type::iterator;
0185 using const_iterator = typename map_type::const_iterator;
0186
0187 virtual ~G4MapCache();
0188
0189
0190 inline G4bool Has(const key_type& k);
0191
0192
0193
0194
0195 inline std::pair<iterator, G4bool> Insert(const key_type& k,
0196 const value_type& v);
0197 inline iterator Begin();
0198 inline iterator End();
0199 inline iterator Find(const key_type& k);
0200 inline value_type& Get(const key_type& k);
0201 inline size_type Erase(const key_type& k);
0202 inline value_type& operator[](const key_type& k);
0203 inline size_type Size() { return G4Cache<map_type>::Get().size(); }
0204
0205 };
0206
0207
0208
0209 template <class V>
0210 G4Cache<V>::G4Cache()
0211 {
0212 G4AutoLock l(G4TypeMutex<G4Cache<V>>());
0213 id = instancesctr++;
0214 #ifdef g4cdebug
0215 std::cout << "G4Cache id: " << id << std::endl;
0216 #endif
0217 }
0218
0219 template <class V>
0220 G4Cache<V>::G4Cache(const G4Cache<V>& rhs)
0221 {
0222
0223
0224
0225 if(this == &rhs)
0226 return;
0227 G4AutoLock l(G4TypeMutex<G4Cache<V>>());
0228 id = instancesctr++;
0229
0230
0231
0232 V aCopy = rhs.GetCache();
0233 Put(aCopy);
0234
0235 #ifdef g4cdebug
0236 std::cout << "Copy constructor with id: " << id << std::endl;
0237 #endif
0238 }
0239
0240 template <class V>
0241 G4Cache<V>& G4Cache<V>::operator=(const G4Cache<V>& rhs)
0242 {
0243 if(this == &rhs)
0244 return *this;
0245
0246
0247
0248 V aCopy = rhs.GetCache();
0249 Put(aCopy);
0250
0251 #ifdef g4cdebug
0252 std::cout << "Assignement operator with id: " << id << std::endl;
0253 #endif
0254 return *this;
0255 }
0256
0257 template <class V>
0258 G4Cache<V>::G4Cache(const V& v)
0259 {
0260 G4AutoLock l(G4TypeMutex<G4Cache<V>>());
0261 id = instancesctr++;
0262 Put(v);
0263
0264 #ifdef g4cdebug
0265 std::cout << "G4Cache id: " << id << std::endl;
0266 #endif
0267 }
0268
0269 template <class V>
0270 G4Cache<V>::~G4Cache()
0271 {
0272 #ifdef g4cdebug
0273 std::cout << "~G4Cache id: " << id << std::endl;
0274 #endif
0275
0276
0277
0278 G4AutoLock l(G4TypeMutex<G4Cache<V>>(), std::defer_lock);
0279
0280
0281
0282 try
0283 {
0284
0285
0286
0287
0288
0289 l.lock();
0290 } catch(std::system_error& e)
0291 {
0292
0293 #ifdef G4VERBOSE
0294 G4cout << "Non-critical error: mutex lock failure in ~G4Cache<"
0295 << typeid(V).name() << ">. " << G4endl
0296 << "If the RunManagerKernel has been deleted, it failed to "
0297 << "delete an allocated resource" << G4endl
0298 << "and this destructor is being called after the statics "
0299 << "were destroyed." << G4endl;
0300 G4cout << "Exception: [code: " << e.code() << "] caught: " << e.what()
0301 << G4endl;
0302 #endif
0303 }
0304 ++dstrctr;
0305 G4bool last = (dstrctr == instancesctr);
0306 theCache.Destroy(id, last);
0307 if(last)
0308 {
0309 instancesctr.store(0);
0310 dstrctr.store(0);
0311 }
0312 }
0313
0314 template <class V>
0315 V& G4Cache<V>::Get() const
0316 {
0317 return GetCache();
0318 }
0319
0320 template <class V>
0321 void G4Cache<V>::Put(const V& val) const
0322 {
0323 GetCache() = val;
0324 }
0325
0326
0327 template <class V>
0328 V G4Cache<V>::Pop()
0329 {
0330 return GetCache();
0331 }
0332
0333 template <class V>
0334 std::atomic<unsigned int> G4Cache<V>::instancesctr(0);
0335
0336 template <class V>
0337 std::atomic<unsigned int> G4Cache<V>::dstrctr(0);
0338
0339
0340
0341 template <class V>
0342 G4VectorCache<V>::G4VectorCache() = default;
0343
0344 template <class V>
0345 G4VectorCache<V>::~G4VectorCache()
0346 {
0347 #ifdef g4cdebug
0348 std::cout << "~G4VectorCache "
0349 << G4Cache<G4VectorCache<V>::vector_type>::GetId()
0350 << " with size: " << Size() << "->";
0351 for(size_type i = 0; i < Size(); ++i)
0352 std::cout << operator[](i) << ",";
0353 std::cout << "<-" << std::endl;
0354 #endif
0355 }
0356
0357 template <class V>
0358 G4VectorCache<V>::G4VectorCache(G4int nElems)
0359 {
0360 vector_type& cc = G4Cache<vector_type>::Get();
0361 cc.resize(nElems);
0362 }
0363
0364 template <class V>
0365 G4VectorCache<V>::G4VectorCache(G4int nElems, V* vals)
0366 {
0367 vector_type& cc = G4Cache<vector_type>::Get();
0368 cc.resize(nElems);
0369 for(G4int idx = 0; idx < nElems; ++idx)
0370 cc[idx] = vals[idx];
0371 }
0372
0373 template <class V>
0374 void G4VectorCache<V>::Push_back(const V& val)
0375 {
0376 G4Cache<vector_type>::Get().push_back(val);
0377 }
0378
0379 template <class V>
0380 V G4VectorCache<V>::Pop_back()
0381 {
0382 vector_type& cc = G4Cache<vector_type>::Get();
0383 value_type val = cc[cc.size() - 1];
0384 cc.pop_back();
0385 return val;
0386 }
0387
0388 template <class V>
0389 V& G4VectorCache<V>::operator[](const G4int& idx)
0390 {
0391 vector_type& cc = G4Cache<vector_type>::Get();
0392 return cc[idx];
0393 }
0394
0395 template <class V>
0396 typename G4VectorCache<V>::iterator G4VectorCache<V>::Begin()
0397 {
0398 return G4Cache<vector_type>::Get().begin();
0399 }
0400
0401 template <class V>
0402 typename G4VectorCache<V>::iterator G4VectorCache<V>::End()
0403 {
0404 return G4Cache<vector_type>::Get().end();
0405 }
0406
0407 template <class V>
0408 void G4VectorCache<V>::Clear()
0409 {
0410 G4Cache<vector_type>::Get().clear();
0411 }
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421 template <class K, class V>
0422 G4MapCache<K, V>::~G4MapCache()
0423 {
0424 #ifdef g4cdebug
0425 std::cout << "~G4MacCache " << G4Cache<map_type>::GetId()
0426 << " with size: " << Size() << "->";
0427 for(iterator it = Begin(); it != End(); ++it)
0428 std::cout << it->first << ":" << it->second << ",";
0429 std::cout << "<-" << std::endl;
0430 #endif
0431 }
0432
0433 template <class K, class V>
0434 std::pair<typename G4MapCache<K, V>::iterator, G4bool> G4MapCache<K, V>::Insert(
0435 const K& k, const V& v)
0436 {
0437 return G4Cache<map_type>::Get().insert(std::pair<key_type, value_type>(k, v));
0438 }
0439
0440
0441
0442
0443
0444
0445
0446 template <class K, class V>
0447 typename G4MapCache<K, V>::iterator G4MapCache<K, V>::Begin()
0448 {
0449 return G4Cache<map_type>::Get().begin();
0450 }
0451 template <class K, class V>
0452 typename G4MapCache<K, V>::iterator G4MapCache<K, V>::End()
0453 {
0454 return G4Cache<map_type>::Get().end();
0455 }
0456
0457 template <class K, class V>
0458 typename G4MapCache<K, V>::iterator G4MapCache<K, V>::Find(const K& k)
0459 {
0460 return G4Cache<map_type>::Get().find(k);
0461 }
0462
0463 template <class K, class V>
0464 G4bool G4MapCache<K, V>::Has(const K& k)
0465 {
0466 return (Find(k) != End());
0467 }
0468
0469 template <class K, class V>
0470 V& G4MapCache<K, V>::Get(const K& k)
0471 {
0472 return Find(k)->second;
0473 }
0474
0475 template <class K, class V>
0476 typename G4MapCache<K, V>::size_type G4MapCache<K, V>::Erase(const K& k)
0477 {
0478 return G4Cache<map_type>::Get().erase(k);
0479 }
0480
0481 template <class K, class V>
0482 V& G4MapCache<K, V>::operator[](const K& k)
0483 {
0484 return (G4Cache<map_type>::Get())[k];
0485 }
0486
0487 #endif