ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4EnhancedVecAllocator.hh
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4EnhancedVecAllocator.hh
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 // Class Description:
27 //
28 // A class for fast allocation of STL vectors through a static pool.
29 // It's meant to be used as alternative allocator for STL vectors.
30 
31 // ---------------- G4EnhancedVecAllocator ----------------
32 //
33 // Original author: X.Dong (NorthEastern Univ.), November 2009
34 // Reviewed implementation: G.Cosmo (CERN), December 2009
35 // ------------------------------------------------------------
36 
37 #ifndef G4EnhancedVecAllocator_h
38 #define G4EnhancedVecAllocator_h 1
39 
40 #include "G4Types.hh"
41 
42 typedef struct
43 {
45  char *address;
46 } G4ChunkType;
47 
48 typedef struct
49 {
50  size_t size;
54 
56 {
57  // --------------------------------------------------------------------
58  // Utility class, placeholder for global data on allocation.
59  // Initialisation to zero of the data below *must* be added ONCE only
60  // directly in the client code, where this allocator is to be applied
61  // --------------------------------------------------------------------
62 
63  public:
64 
68 };
69 
70 template<typename _Tp>
71 class G4EnhancedVecAllocator : public std::allocator<_Tp>
72 {
73  public:
74 
75  template<typename _Tp1>
77 
79 
81  : std::allocator<_Tp>() {;}
82 
83  template<typename _Tp1>
85  : std::allocator<_Tp>() {;}
86 
88 
89  // override allocate / deallocate
90  //
91  void deallocate(_Tp* _Ptr, size_t _Count);
92 #ifdef __IBMCPP__
93  _Tp* allocate(size_t _Count, void * const hint = 0); // IBM AIX
94 #else
95  _Tp* allocate(size_t _Count);
96 #endif
97 };
98 
99 // ------------------------------------------------------------
100 // Inline implementations
101 // ------------------------------------------------------------
102 
103 // ************************************************************
104 // deallocate
105 // ************************************************************
106 //
107 template<typename _Tp>
108 void G4EnhancedVecAllocator<_Tp>::deallocate(_Tp* _Ptr, size_t _Count)
109 {
110  G4int found = -1;
111  if (G4AllocStats::allocStat != 0)
112  {
113  for (auto j = 0 ; j < G4AllocStats::numCat ; ++j)
114  {
115  if (G4AllocStats::allocStat[j].size == (_Count * sizeof(_Tp)))
116  {
117  found = j;
118  break;
119  }
120  }
121  }
122  // assert(found != -1);
123 
125 
126  for (auto k = 0; k < chunk.totalspace; ++k)
127  {
128  if ( (chunk.preAllocated[k]).address == ((char *) _Ptr))
129  {
130  // assert((chunk.preAllocated[k]).isAllocated==1);
131  (chunk.preAllocated[k]).isAllocated = 0;
132  return;
133  }
134  }
135 }
136 
137 // ************************************************************
138 // allocate
139 // ************************************************************
140 //
141 #ifdef __IBMCPP__
142 template<typename _Tp>
143 _Tp* G4EnhancedVecAllocator<_Tp>::allocate(size_t _Count, void * const hint)
144 #else
145 template<typename _Tp>
147 #endif
148 {
149  size_t totalsize = _Count * sizeof(_Tp);
150 
151  G4int found = -1;
152  if (G4AllocStats::allocStat != 0)
153  {
154  for (auto j = 0 ; j < G4AllocStats::numCat ; ++j)
155  {
156  if (G4AllocStats::allocStat[j].size == totalsize)
157  {
158  found = j;
159  break;
160  }
161  }
162  }
163 
164  if (found == -1) // Find the new size
165  {
168  {
170  // heuristic parameter for different sizes
171 
175  // This value must be different than zero; otherwise means
176  // failure in allocating extra space !
177  // assert(G4AllocStats::allocStat != 0);
178  }
179 
183 
184  found = G4AllocStats::numCat - 1;
186 
187  chunk.totalspace = 512;
188  // heuristic for the number of STL vector instances
189 
190  chunk.preAllocated = (G4ChunkType *) realloc(chunk.preAllocated,
191  sizeof(G4ChunkType) * chunk.totalspace);
192  // This value must be different than zero; otherwise means
193  // failure in allocating extra space for pointers !
194  // assert(chunk.preAllocated != 0);
195 
196  char *newSpace1 = (char *) malloc(totalsize * 512);
197  // This pointer must be different than zero; otherwise means
198  // failure in allocating extra space for instances !
199  // assert(newSpace1 != 0);
200 
201  for (auto k = 0; k < 512 ; ++k)
202  {
203  (chunk.preAllocated[k]).isAllocated = 0;
204  (chunk.preAllocated[k]).address = newSpace1+totalsize*k;
205  }
206 
207  (chunk.preAllocated[0]).isAllocated = 1;
208  return (_Tp*)((chunk.preAllocated[0]).address);
209  }
210 
212 
213  // assert(chunk.size == totalsize);
214 
215  for (auto k = 0; k < chunk.totalspace; ++k)
216  {
217  if ((chunk.preAllocated[k]).isAllocated == 0)
218  {
219  (chunk.preAllocated[k]).isAllocated = 1;
220  return (_Tp*)((chunk.preAllocated[k]).address);
221  }
222  }
223 
224  G4int originalchunknumber = chunk.totalspace;
225 
226  chunk.totalspace += 512; // heuristic for the number of STL vector instances
227 
228  chunk.preAllocated = (G4ChunkType *) realloc(chunk.preAllocated,
229  sizeof(G4ChunkType) * chunk.totalspace);
230  // This value must be different than zero; otherwise means
231  // failure in allocating extra space for pointers !
232  // assert(chunk.preAllocated != 0);
233 
234  char *newSpace = (char *) malloc(totalsize * 512);
235  // This pointer must be different than zero; otherwise means
236  // failure in allocating extra space for instances !
237  // assert(newSpace != 0);
238 
239  for (auto k = 0; k < 512 ; ++k)
240  {
241  (chunk.preAllocated[originalchunknumber+k]).isAllocated = 0;
242  (chunk.preAllocated[originalchunknumber+k]).address = newSpace+totalsize*k;
243  }
244 
245  (chunk.preAllocated[originalchunknumber]).isAllocated = 1;
246 
247  return (_Tp*)((chunk.preAllocated[originalchunknumber]).address);
248 }
249 
250 // ************************************************************
251 // operator==
252 // ************************************************************
253 //
254 template<typename _T1, typename _T2>
257 { return true; }
258 
259 // ************************************************************
260 // operator!=
261 // ************************************************************
262 //
263 template<typename _T1, typename _T2>
266 { return false; }
267 
268 #endif