File indexing completed on 2026-09-21 09:09:58
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 theCache.Initialize(id);
0215 #ifdef g4cdebug
0216 std::cout << "G4Cache id: " << id << std::endl;
0217 #endif
0218 }
0219
0220 template <class V>
0221 G4Cache<V>::G4Cache(const G4Cache<V>& rhs)
0222 {
0223
0224
0225
0226 if(this == &rhs)
0227 return;
0228 G4AutoLock l(G4TypeMutex<G4Cache<V>>());
0229 id = instancesctr++;
0230
0231
0232
0233 V aCopy = rhs.GetCache();
0234 Put(aCopy);
0235
0236 #ifdef g4cdebug
0237 std::cout << "Copy constructor with id: " << id << std::endl;
0238 #endif
0239 }
0240
0241 template <class V>
0242 G4Cache<V>& G4Cache<V>::operator=(const G4Cache<V>& rhs)
0243 {
0244 if(this == &rhs)
0245 return *this;
0246
0247
0248
0249 V aCopy = rhs.GetCache();
0250 Put(aCopy);
0251
0252 #ifdef g4cdebug
0253 std::cout << "Assignement operator with id: " << id << std::endl;
0254 #endif
0255 return *this;
0256 }
0257
0258 template <class V>
0259 G4Cache<V>::G4Cache(const V& v)
0260 {
0261 G4AutoLock l(G4TypeMutex<G4Cache<V>>());
0262 id = instancesctr++;
0263 Put(v);
0264
0265 #ifdef g4cdebug
0266 std::cout << "G4Cache id: " << id << std::endl;
0267 #endif
0268 }
0269
0270 template <class V>
0271 G4Cache<V>::~G4Cache()
0272 {
0273 #ifdef g4cdebug
0274 std::cout << "~G4Cache id: " << id << std::endl;
0275 #endif
0276
0277
0278
0279 G4AutoLock l(G4TypeMutex<G4Cache<V>>(), std::defer_lock);
0280
0281
0282
0283 try
0284 {
0285
0286
0287
0288
0289
0290 l.lock();
0291 } catch(std::system_error& e)
0292 {
0293
0294 #ifdef g4cdebug
0295 std::cout << "Non-critical error: mutex lock failure in ~G4Cache<"
0296 << typeid(V).name() << ">. " << std::endl
0297 << "If the RunManagerKernel has been deleted, it failed to "
0298 << "delete an allocated resource" << std::endl
0299 << "and this destructor is being called after the statics "
0300 << "were destroyed." << std::endl;
0301 std::cout << "Exception: [code: " << e.code() << "] caught: " << e.what()
0302 << std::endl;
0303 #endif
0304 }
0305 ++dstrctr;
0306 G4bool last = (dstrctr == instancesctr);
0307 theCache.Destroy(id, last);
0308 if(last)
0309 {
0310 instancesctr.store(0);
0311 dstrctr.store(0);
0312 }
0313 }
0314
0315 template <class V>
0316 V& G4Cache<V>::Get() const
0317 {
0318 return GetCache();
0319 }
0320
0321 template <class V>
0322 void G4Cache<V>::Put(const V& val) const
0323 {
0324 GetCache() = val;
0325 }
0326
0327
0328 template <class V>
0329 V G4Cache<V>::Pop()
0330 {
0331 return GetCache();
0332 }
0333
0334 template <class V>
0335 std::atomic<unsigned int> G4Cache<V>::instancesctr(0);
0336
0337 template <class V>
0338 std::atomic<unsigned int> G4Cache<V>::dstrctr(0);
0339
0340
0341
0342 template <class V>
0343 G4VectorCache<V>::G4VectorCache() = default;
0344
0345 template <class V>
0346 G4VectorCache<V>::~G4VectorCache()
0347 {
0348 #ifdef g4cdebug
0349 std::cout << "~G4VectorCache "
0350 << G4Cache<G4VectorCache<V>::vector_type>::GetId()
0351 << " with size: " << Size() << "->";
0352 for(size_type i = 0; i < Size(); ++i)
0353 std::cout << operator[](i) << ",";
0354 std::cout << "<-" << std::endl;
0355 #endif
0356 }
0357
0358 template <class V>
0359 G4VectorCache<V>::G4VectorCache(G4int nElems)
0360 {
0361 vector_type& cc = G4Cache<vector_type>::Get();
0362 cc.resize(nElems);
0363 }
0364
0365 template <class V>
0366 G4VectorCache<V>::G4VectorCache(G4int nElems, V* vals)
0367 {
0368 vector_type& cc = G4Cache<vector_type>::Get();
0369 cc.resize(nElems);
0370 for(G4int idx = 0; idx < nElems; ++idx)
0371 cc[idx] = vals[idx];
0372 }
0373
0374 template <class V>
0375 void G4VectorCache<V>::Push_back(const V& val)
0376 {
0377 G4Cache<vector_type>::Get().push_back(val);
0378 }
0379
0380 template <class V>
0381 V G4VectorCache<V>::Pop_back()
0382 {
0383 vector_type& cc = G4Cache<vector_type>::Get();
0384 value_type val = cc[cc.size() - 1];
0385 cc.pop_back();
0386 return val;
0387 }
0388
0389 template <class V>
0390 V& G4VectorCache<V>::operator[](const G4int& idx)
0391 {
0392 vector_type& cc = G4Cache<vector_type>::Get();
0393 return cc[idx];
0394 }
0395
0396 template <class V>
0397 typename G4VectorCache<V>::iterator G4VectorCache<V>::Begin()
0398 {
0399 return G4Cache<vector_type>::Get().begin();
0400 }
0401
0402 template <class V>
0403 typename G4VectorCache<V>::iterator G4VectorCache<V>::End()
0404 {
0405 return G4Cache<vector_type>::Get().end();
0406 }
0407
0408 template <class V>
0409 void G4VectorCache<V>::Clear()
0410 {
0411 G4Cache<vector_type>::Get().clear();
0412 }
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422 template <class K, class V>
0423 G4MapCache<K, V>::~G4MapCache()
0424 {
0425 #ifdef g4cdebug
0426 std::cout << "~G4MacCache " << G4Cache<map_type>::GetId()
0427 << " with size: " << Size() << "->";
0428 for(iterator it = Begin(); it != End(); ++it)
0429 std::cout << it->first << ":" << it->second << ",";
0430 std::cout << "<-" << std::endl;
0431 #endif
0432 }
0433
0434 template <class K, class V>
0435 std::pair<typename G4MapCache<K, V>::iterator, G4bool> G4MapCache<K, V>::Insert(
0436 const K& k, const V& v)
0437 {
0438 return G4Cache<map_type>::Get().insert(std::pair<key_type, value_type>(k, v));
0439 }
0440
0441
0442
0443
0444
0445
0446
0447 template <class K, class V>
0448 typename G4MapCache<K, V>::iterator G4MapCache<K, V>::Begin()
0449 {
0450 return G4Cache<map_type>::Get().begin();
0451 }
0452 template <class K, class V>
0453 typename G4MapCache<K, V>::iterator G4MapCache<K, V>::End()
0454 {
0455 return G4Cache<map_type>::Get().end();
0456 }
0457
0458 template <class K, class V>
0459 typename G4MapCache<K, V>::iterator G4MapCache<K, V>::Find(const K& k)
0460 {
0461 return G4Cache<map_type>::Get().find(k);
0462 }
0463
0464 template <class K, class V>
0465 G4bool G4MapCache<K, V>::Has(const K& k)
0466 {
0467 return (Find(k) != End());
0468 }
0469
0470 template <class K, class V>
0471 V& G4MapCache<K, V>::Get(const K& k)
0472 {
0473 return Find(k)->second;
0474 }
0475
0476 template <class K, class V>
0477 typename G4MapCache<K, V>::size_type G4MapCache<K, V>::Erase(const K& k)
0478 {
0479 return G4Cache<map_type>::Get().erase(k);
0480 }
0481
0482 template <class K, class V>
0483 V& G4MapCache<K, V>::operator[](const K& k)
0484 {
0485 return (G4Cache<map_type>::Get())[k];
0486 }
0487
0488 #endif