Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/global/management/include/G4CacheDetails.hh

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 // G4CacheDetails
 27 //
 28 // Class description:
 29 //
 30 //    The classes contained in this header files are used by
 31 //    G4Cache to store a TLS instance of the cached object.
 32 //    These classes should not be used by client code, but
 33 //    are used by one of the G4Cache classes.
 34 //
 35 //    G4Cache is a container of the cached value.
 36 //    Not memory efficient, but CPU efficient (constant time access).
 37 //    A different version with a map instead of a vector should be
 38 //    memory efficient and less CPU efficient (log-time access).
 39 //    If really a lot of these objects are used
 40 //    we may want to consider the map version to save some memory.
 41 //
 42 //    These are simplified "split-classes" without any
 43 //    copy-from-master logic. Each cached object is associated
 44 //    a unique identified (an integer), that references an instance
 45 //    of the cached value (of template type VALTYPE) in a
 46 //    static TLS data structure.
 47 //
 48 //    In case the cache is used for a cached object the object class
 49 //    has to provide a default constructor. Alternatively pointers to
 50 //    objects can be stored in the cache and this limitation is removed
 51 //    but explicit handling of memory (new/delete) of cached object becomes
 52 //    client responsibility.
 53 //
 54 // Todos: - Understand if map based class can be more efficent than
 55 //          vector one.
 56 //        - Evaluate use of specialized allocator for TLS "new".
 57 
 58 // Author: A.Dotti, 21 October 2013 - First implementation
 59 // --------------------------------------------------------------------
 60 #ifndef G4CacheDetails_hh
 61 #define G4CacheDetails_hh
 62 
 63 #include "G4Threading.hh"
 64 #include "globals.hh"
 65 #include <vector>
 66 
 67 // A TLS storage for a cache of type VALTYPE
 68 //
 69 template <class VALTYPE>
 70 class G4CacheReference
 71 {
 72  public:
 73   inline void Initialize(unsigned int id);
 74   // Initliaze TLS storage
 75 
 76   inline void Destroy(unsigned int id, G4bool last);
 77   // Cleanup TLS storage for instance id. If last==true
 78   // destroy and cleanup object container
 79 
 80   inline VALTYPE& GetCache(unsigned int id) const;
 81   // Returns cached value for instance id
 82 
 83  private:
 84   using cache_container = std::vector<VALTYPE*>;
 85   // Implementation detail: the cached object is stored as a
 86   // pointer. Object is stored as a pointer to avoid too large
 87   // std::vector in case of stored objects and allow use of
 88   // specialized allocators
 89 
 90   static cache_container*& cache();
 91 };
 92 
 93 // Template specialization for pointers
 94 // Note: Objects are not owned by cache, for this version of the cache
 95 //       the explicit new/delete of the cached object
 96 //
 97 template <class VALTYPE>
 98 class G4CacheReference<VALTYPE*>
 99 {
100  public:
101   inline void Initialize(unsigned int id);
102 
103   inline void Destroy(unsigned int id, G4bool last);
104 
105   inline VALTYPE*& GetCache(unsigned int id) const;
106 
107  private:
108   using cache_container = std::vector<VALTYPE*>;
109   static cache_container*& cache();
110 };
111 
112 // Template specialization for probably the most used case: double
113 // Be more efficient avoiding unnecessary "new/delete"
114 //
115 template <>
116 class G4CacheReference<G4double>
117 {
118  public:
119   inline void Initialize(unsigned int id);
120 
121   inline void Destroy(unsigned int id, G4bool last);
122 
123   inline G4double& GetCache(unsigned int id) const;
124 
125  private:
126   using cache_container = std::vector<G4double>;
127   static G4GLOB_DLL cache_container*& cache();
128 };
129 
130 //======= Implementation: G4CacheReference<V>
131 //===========================================
132 
133 template <class V>
134 void G4CacheReference<V>::Initialize(unsigned int id)
135 {
136   // Create cache container
137   if(cache() == nullptr)
138   {
139 #ifdef g4cdebug
140     std::cout << "Generic template container..." << std::endl;
141 #endif
142     cache() = new cache_container;
143   }
144   if(cache()->size() <= id)
145   {
146     cache()->resize(id + 1, static_cast<V*>(0));
147   }
148   if((*cache())[id] == 0)
149   {
150     (*cache())[id] = new V;
151   }
152 }
153 
154 template <class V>
155 void G4CacheReference<V>::Destroy(unsigned int id, G4bool last)
156 {
157   if(cache() != nullptr)
158   {
159 #ifdef g4cdebug
160     std::cout << "V: Destroying element " << id << " is last? " << last
161               << std::endl;
162 #endif
163     if(cache()->size() < id)
164     {
165       G4ExceptionDescription msg;
166       msg << "Internal fatal error. Invalid G4Cache size (requested id: " << id
167           << " but cache has size: " << cache()->size();
168       msg << " Possibly client created G4Cache object in a thread and"
169           << " tried to delete it from another thread!";
170       G4Exception("G4CacheReference<V>::Destroy", "Cache001", FatalException,
171                   msg);
172       return;
173     }
174     if(cache()->size() > id && (*cache())[id] != nullptr)
175     {
176 #ifdef g4cdebug
177       std::cout << "V: Destroying element " << id
178                 << " size: " << cache()->size() << std::endl;
179 #endif
180       delete(*cache())[id];
181       (*cache())[id] = nullptr;
182     }
183     if(last)
184     {
185 #ifdef g4cdebug
186       std::cout << "V: Destroying LAST element!" << std::endl;
187 #endif
188       delete cache();
189       cache() = nullptr;
190     }
191   }
192 }
193 
194 template <class V>
195 V& G4CacheReference<V>::GetCache(unsigned int id) const
196 {
197   return *(cache()->operator[](id));
198 }
199 
200 template <class V>
201 typename G4CacheReference<V>::cache_container*& G4CacheReference<V>::cache()
202 {
203   G4ThreadLocalStatic cache_container* _instance = nullptr;
204   return _instance;
205 }
206 
207 //======= Implementation: G4CacheReference<V*>
208 //============================================
209 
210 template <class V>
211 void G4CacheReference<V*>::Initialize(unsigned int id)
212 {
213   if(cache() == nullptr)
214   {
215 #ifdef g4cdebug
216     std::cout << "Pointer template container..." << std::endl;
217 #endif
218     cache() = new cache_container;
219   }
220   if(cache()->size() <= id)
221   {
222     cache()->resize(id + 1, static_cast<V*>(nullptr));
223   }
224 }
225 
226 template <class V>
227 inline void G4CacheReference<V*>::Destroy(unsigned int id, G4bool last)
228 {
229   if(cache() != nullptr)
230   {
231 #ifdef g4cdebug
232     std::cout << "V*: Destroying element " << id << " is last? " << last
233               << std::endl;
234 #endif
235     if(cache()->size() < id)
236     {
237       G4ExceptionDescription msg;
238       msg << "Internal fatal error. Invalid G4Cache size (requested id: " << id
239           << " but cache has size: " << cache()->size();
240       msg << " Possibly client created G4Cache object in a thread and"
241           << " tried to delete it from another thread!";
242       G4Exception("G4CacheReference<V*>::Destroy", "Cache001", FatalException,
243                   msg);
244       return;
245     }
246     if(cache()->size() > id && (*cache())[id] != nullptr)
247     {
248       // Ownership is for client
249       // delete (*cache())[id];
250 #ifdef g4cdebug
251       std::cout << "V*: Resetting element " << id
252                 << " size: " << cache()->size() << std::endl;
253 #endif
254       (*cache())[id] = nullptr;
255     }
256     if(last)
257     {
258 #ifdef g4cdebug
259       std::cout << "V*: Deleting LAST element!" << std::endl;
260 #endif
261       delete cache();
262       cache() = nullptr;
263     }
264   }
265 }
266 
267 template <class V>
268 V*& G4CacheReference<V*>::GetCache(unsigned int id) const
269 {
270   return (cache()->operator[](id));
271 }
272 
273 template <class V>
274 typename G4CacheReference<V*>::cache_container*& G4CacheReference<V*>::cache()
275 {
276   G4ThreadLocalStatic cache_container* _instance = nullptr;
277   return _instance;
278 }
279 
280 //======= Implementation: G4CacheReference<double>
281 //============================================
282 
283 void G4CacheReference<G4double>::Initialize(unsigned int id)
284 {
285   if(cache() == nullptr)
286   {
287 #ifdef g4cdebug
288     std::cout << "Specialized template for G4double container..." << std::endl;
289 #endif
290     cache() = new cache_container;
291   }
292   if(cache()->size() <= id)
293   {
294     cache()->resize(id + 1, static_cast<G4double>(0));
295   }
296 }
297 
298 void G4CacheReference<G4double>::Destroy(unsigned int /*id*/, G4bool last)
299 {
300   if(cache() != nullptr && last)
301   {
302 #ifdef g4cdebug
303     std::cout << "DB: Destroying LAST element! Is it last? " << last
304               << std::endl;
305 #endif
306     delete cache();
307     cache() = nullptr;
308   }
309 }
310 
311 G4double& G4CacheReference<G4double>::GetCache(unsigned int id) const
312 {
313   return cache()->operator[](id);
314 }
315 
316 #endif
317