ATLAS Offline Software
LWPools.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include <atomic>
6 #ifdef LW_DEBUG_POOLS_DEBUG_USAGE
7 #include <iostream>
8 #include <map>
9 #include <mutex>
10 #endif
11 
12 //____________________________________________________________________
13 class LWPools::PoolList {
14  //basically an array of pools which inits to null
15 public:
16  std::atomic<LWPool*>& operator[](unsigned i) { return m_poolarr[i]; }
17  const LWPool * operator[](unsigned i) const { return m_poolarr[i].load(); }
18  PoolList();
19  void cleanup();
20 #ifdef LW_DEBUG_POOLS_DEBUG_USAGE
21  std::map<char*,unsigned> m_memoryHandedOut;
22  std::mutex m_mutex;
23 #endif
24 private:
25  void nullout();
26  std::atomic<LWPool*> m_poolarr[LWPoolSelector::numberOfPools];
27 };
28 
29 //____________________________________________________________________
30 inline LWPool * LWPools::getPool(unsigned length)
31 {
32  assert(length>0);
33  unsigned idx = LWPoolSelector::poolIndex(length);
34  if (idx==UINT_MAX)
35  return 0;
36  LWPool * pool = s_pools[idx];
37  return pool ? pool : initPool(idx,length);
38 }
39 
40 //____________________________________________________________________
41 inline char * LWPools::acquire(unsigned length)
42 {
43  assert(length>0);
44  char * c;
45 #ifdef LW_DEBUG_POOLS_USE_NEW
46  s_bytesDynAlloc += length;
47  c = new char[length];
48 #else
49  LWPool * pool = getPool(length);
50  if (pool) {
51  c = pool->acquire();
52  } else {
53  s_bytesDynAlloc += length;
54  c = new char[length];
55  }
56 #endif
57 
58 #ifdef LW_DEBUG_POOLS_DEBUG_USAGE
59  std::scoped_lock lock (m_mutex);
60  std::map<char*,unsigned>::const_iterator it = s_pools.m_memoryHandedOut.find(c);
61  if (it!=s_pools.m_memoryHandedOut.end()) {
62  std::cout<<"LWPools::acquire("<<length<<") INTERNAL ERROR: Handing out the same address ("<<(void*)c<<") twice!!"<<std::endl;
63  assert(false);
64  } else {
65  s_pools.m_memoryHandedOut[c] = length;
66  }
67 #endif
68 
69  return c;
70 }
71 
72 //____________________________________________________________________
73 inline void LWPools::release(char*c,unsigned length)
74 {
75 #ifdef LW_DEBUG_POOLS_DEBUG_USAGE
76  std::scoped_lock lock (m_mutex);
77  if (!c||length==0)
78  std::cout<<"LWPools::release("<<(void*)c<<", "<<length<<")"<<std::endl;
79  std::map<char*,unsigned>::iterator it = s_pools.m_memoryHandedOut.find(c);
80  if (it==s_pools.m_memoryHandedOut.end()) {
81  std::cout<<"LWPools::release("<<(void*)c<<", "<<length<<") ERROR:"
82  <<" Releasing address which was never acquired"<<std::endl;
83  assert(false);
84  } else {
85  if (length!=it->second) {
86  std::cout<<"LWPools::release("<<(void*)c<<", "<<length<<") ERROR:"
87  <<" Releasing address of length "<<length
88  <<" which was previously acquired with length "<<it->second<<std::endl;
89  assert(false);
90  }
91  s_pools.m_memoryHandedOut.erase(it);
92  }
93 #endif
94  assert(c&&length>0);
95 #ifdef LW_DEBUG_POOLS_USE_NEW
96  s_bytesDynAlloc -= length;
97  delete[] c;
98  return;
99 #endif
100  LWPool * pool = getPool(length);
101  if (pool) {
102  pool->release(c);
103  } else {
104  s_bytesDynAlloc -= length;
105  delete[] c;
106  }
107 }
108 
109 template<class T, unsigned length>
110 inline T* LWPools::acquire()
111 {
112  T* t = reinterpret_cast<T*>(acquire<sizeof(T)*length>());
113  return t;
114 }
115 
116 template<class T, unsigned length>
117 inline void LWPools::release(T*t)
118 {
119  release<sizeof(T)*length>(reinterpret_cast<char*>(t));
120 }
121 
122 template<class T>
123 inline T * LWPools::acquire(unsigned length)
124 {
125  return reinterpret_cast<T*>(acquire(sizeof(T)*length));
126 }
127 
128 template<class T>
129 inline void LWPools::release(T*t,unsigned length)
130 {
131  release( reinterpret_cast<char*>(t),sizeof(T)*length);
132 }
133 
134 template<class T> inline void LWPools::deleteObject(T*t)
135 {
136  if (t) {
137  t->~T();
138  release<sizeof(T)>(reinterpret_cast<char*>(t));
139  }
140 }