]> git.ipfire.org Git - thirdparty/squid.git/blame - include/MemPool.h
Fix a forgotten change during recent comm layer rework
[thirdparty/squid.git] / include / MemPool.h
CommitLineData
d96ceb8e 1
2#ifndef _MEM_POOLS_H_
3#define _MEM_POOLS_H_
4
5#include "config.h"
f323a09d 6#include "assert.h"
d96ceb8e 7#include "util.h"
83d8f9f4 8
d96ceb8e 9#include "memMeter.h"
b001e822 10#include "splay.h"
d96ceb8e 11
12#if HAVE_GNUMALLOC_H
13#include <gnumalloc.h>
482aa790 14#elif HAVE_MALLOC_H
d96ceb8e 15#include <malloc.h>
16#endif
17
18#if HAVE_MEMORY_H
19#include <memory.h>
20#endif
21
22#if !M_MMAP_MAX
23#if USE_DLMALLOC
24#define M_MMAP_MAX -4
25#endif
26#endif
27
d96ceb8e 28#define MB ((size_t)1024*1024)
29#define mem_unlimited_size 2 * 1024 * MB
30#define toMB(size) ( ((double) size) / MB )
31#define toKB(size) ( (size + 1024 - 1) / 1024 )
32
33#define MEM_PAGE_SIZE 4096
34#define MEM_CHUNK_SIZE 4096 * 4
35#define MEM_CHUNK_MAX_SIZE 256 * 1024 /* 2MB */
36#define MEM_MIN_FREE 32
37#define MEM_MAX_FREE 65535 /* ushort is max number of items per chunk */
38
b001e822 39class MemImplementingAllocator;
40class MemChunk;
41class MemPoolStats;
83d8f9f4 42
d96ceb8e 43typedef struct _MemPoolGlobalStats MemPoolGlobalStats;
83d8f9f4 44
b001e822 45class MemPoolIterator
83d8f9f4 46{
b001e822 47 public:
48 MemImplementingAllocator *pool;
d96ceb8e 49 MemPoolIterator * next;
50};
51
52/* object to track per-pool cumulative counters */
83d8f9f4 53
b001e822 54class mgb_t
83d8f9f4 55{
b001e822 56 public:
57 mgb_t() : count(0), bytes(0){}
d96ceb8e 58 double count;
59 double bytes;
b001e822 60};
d96ceb8e 61
62/* object to track per-pool memory usage (alloc = inuse+idle) */
83d8f9f4 63
b001e822 64class MemPoolMeter
83d8f9f4 65{
b001e822 66 public:
67 void flush();
d96ceb8e 68 MemMeter alloc;
69 MemMeter inuse;
70 MemMeter idle;
71 mgb_t gb_saved; /* account Allocations */
72 mgb_t gb_osaved; /* history Allocations */
73 mgb_t gb_freed; /* account Free calls */
74};
75
b001e822 76class MemImplementingAllocator;
77
78class MemPools
79{
80 public:
81 static MemPools &GetInstance();
82 MemPools();
83 void init();
84 void flushMeters();
85 MemImplementingAllocator * create(const char *label, size_t obj_size);
86 MemImplementingAllocator * create(const char *label, size_t obj_size, bool const chunked);
87 void setIdleLimit(size_t new_idle_limit);
88 size_t const idleLimit() const;
89 void clean(time_t maxage);
90 void setDefaultPoolChunking(bool const &);
91 MemImplementingAllocator *pools;
92 int mem_idle_limit;
93 int poolCount;
94 bool defaultIsChunked;
95 private:
96 static MemPools *Instance;
97};
98
d96ceb8e 99/* a pool is a [growing] space for objects of the same size */
83d8f9f4 100
b001e822 101class MemAllocator
102{
103public:
104 MemAllocator (char const *aLabel);
105 virtual ~MemAllocator() {}
106 virtual int getStats(MemPoolStats * stats) = 0;
107 virtual MemPoolMeter const &getMeter() const = 0;
108 virtual void *alloc() = 0;
109 virtual void free(void *) = 0;
110 virtual char const *objectType() const;
111 virtual size_t objectSize() const = 0;
a3efa961 112 int inUseCount();
04eb0689 113 virtual void setChunkSize(size_t chunksize) {}
b001e822 114private:
115 const char *label;
116};
117
118/* Support late binding of pool type for allocator agnostic classes */
119class MemAllocatorProxy
83d8f9f4 120{
b001e822 121 public:
122 inline MemAllocatorProxy(char const *aLabel, size_t const &);
123 void *alloc();
124 void free(void *);
125 int inUseCount() const;
126 size_t objectSize() const;
127 MemPoolMeter const &getMeter() const;
128 int getStats(MemPoolStats * stats);
129 char const * objectType() const;
130 private:
131 MemAllocator *getAllocator() const;
d96ceb8e 132 const char *label;
b001e822 133 size_t size;
134 mutable MemAllocator *theAllocator;
135};
136/* help for classes */
137/* Put this in the class */
138#define MEMPROXY_CLASS(CLASS) \
139/* TODO change syntax to allow moving into .cci files */ \
140 inline void *operator new(size_t); \
141 inline void operator delete(void *); \
142 static inline MemAllocatorProxy &Pool()
143
144/* put this in the class .h, or .cci as appropriate */
145#define MEMPROXY_CLASS_INLINE(CLASS) \
146MemAllocatorProxy& CLASS::Pool() \
147{ \
148 static MemAllocatorProxy thePool(#CLASS, sizeof (CLASS)); \
149 return thePool; \
150} \
151\
152void * \
153CLASS::operator new (size_t byteCount) \
154{ \
155 /* derived classes with different sizes must implement their own new */ \
156 assert (byteCount == sizeof (CLASS)); \
157\
158 return Pool().alloc(); \
159} \
160\
161void \
162CLASS::operator delete (void *address) \
163{ \
164 Pool().free(address); \
165}
166
167class MemImplementingAllocator : public MemAllocator
168{
169 public:
170 MemImplementingAllocator(char const *aLabel, size_t aSize);
171 virtual MemPoolMeter const &getMeter() const;
172 virtual MemPoolMeter &getMeter();
173 virtual void flushMetersFull();
174 virtual void flushMeters();
175 virtual void *alloc();
176 virtual void free(void *);
177 virtual bool idleTrigger(int shift) const = 0;
178 virtual void clean(time_t maxage) = 0;
179 /* Hint to the allocator - may be ignored */
180 virtual void setChunkSize(size_t chunksize) {}
181 virtual size_t objectSize() const;
182 protected:
183 virtual void *allocate() = 0;
184 virtual void deallocate(void *) = 0;
185 private:
186 MemPoolMeter meter;
187 public:
188 MemImplementingAllocator *next;
189 public:
190 size_t alloc_calls;
191 size_t free_calls;
d96ceb8e 192 size_t obj_size;
b001e822 193};
194
195class MemPool : public MemImplementingAllocator
196{
197 public:
198 friend class MemChunk;
199 MemPool(const char *label, size_t obj_size);
200 ~MemPool();
201 void convertFreeCacheToChunkFreeCache();
202 virtual void clean(time_t maxage);
203 virtual int getStats(MemPoolStats * stats);
204 void createChunk();
205 void *get();
206 void push(void *obj);
207 protected:
208 virtual void *allocate();
209 virtual void deallocate(void *);
210 public:
211 virtual void setChunkSize(size_t chunksize);
212 virtual bool idleTrigger(int shift) const;
213
d96ceb8e 214 size_t chunk_size;
215 int chunk_capacity;
216 int memPID;
217 int chunkCount;
d96ceb8e 218 size_t inuse;
219 size_t idle;
220 void *freeCache;
221 MemChunk *nextFreeChunk;
222 MemChunk *Chunks;
b001e822 223 Splay<MemChunk *> allChunks;
224};
225
226class MemMalloc : public MemImplementingAllocator
227{
228 public:
229 MemMalloc(char const *label, size_t aSize);
230 virtual bool idleTrigger(int shift) const;
231 virtual void clean(time_t maxage);
232 virtual int getStats(MemPoolStats * stats);
233 protected:
234 virtual void *allocate();
235 virtual void deallocate(void *);
d96ceb8e 236};
237
b001e822 238class MemChunk
83d8f9f4 239{
b001e822 240 public:
241 MemChunk(MemPool *pool);
242 ~MemChunk();
d96ceb8e 243 void *freeList;
244 void *objCache;
245 int inuse_count;
246 MemChunk *nextFreeChunk;
247 MemChunk *next;
248 time_t lastref;
b001e822 249 MemPool *pool;
d96ceb8e 250};
251
b001e822 252class MemPoolStats
83d8f9f4 253{
b001e822 254 public:
255 MemAllocator *pool;
d96ceb8e 256 const char *label;
257 MemPoolMeter *meter;
258 int obj_size;
259 int chunk_capacity;
260 int chunk_size;
261
262 int chunks_alloc;
263 int chunks_inuse;
264 int chunks_partial;
265 int chunks_free;
266
267 int items_alloc;
268 int items_inuse;
269 int items_idle;
270
271 int overhead;
272};
273
83d8f9f4 274struct _MemPoolGlobalStats
275{
d96ceb8e 276 MemPoolMeter *TheMeter;
277
278 int tot_pools_alloc;
279 int tot_pools_inuse;
280 int tot_pools_mempid;
281
282 int tot_chunks_alloc;
283 int tot_chunks_inuse;
284 int tot_chunks_partial;
285 int tot_chunks_free;
286
287 int tot_items_alloc;
288 int tot_items_inuse;
289 int tot_items_idle;
290
291 int tot_overhead;
292 int mem_idle_limit;
293};
294
295#define SIZEOF_CHUNK ( ( sizeof(MemChunk) + sizeof(double) -1) / sizeof(double) ) * sizeof(double);
296
04eb0689 297#define memPoolCreate MemPools::GetInstance().create
298
d96ceb8e 299/* Allocator API */
b001e822 300extern MemPoolIterator * memPoolIterate(void);
301extern MemImplementingAllocator * memPoolIterateNext(MemPoolIterator * iter);
302extern void memPoolIterateDone(MemPoolIterator ** iter);
d96ceb8e 303
b001e822 304/* Stats API - not sured how to refactor yet */
305extern int memPoolGetGlobalStats(MemPoolGlobalStats * stats);
d96ceb8e 306
b001e822 307extern int memPoolInUseCount(MemAllocator *);
308extern int memPoolsTotalAllocated(void);
d96ceb8e 309
b001e822 310MemAllocatorProxy::MemAllocatorProxy(char const *aLabel, size_t const &aSize) : label (aLabel), size(aSize), theAllocator (NULL)
311{
312}
d96ceb8e 313
d96ceb8e 314
315#endif /* _MEM_POOLS_H_ */