]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/MemPool.cc
5 * DEBUG: section 63 Low Level Memory Pool Management
6 * AUTHOR: Alex Rousskov, Andres Kroonmaa, Robert Collins
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * the Regents of the University of California. Please see the
16 * COPYRIGHT file for full details. Squid incorporates software
17 * developed and/or copyrighted by other sources. Please see the
18 * CREDITS file for full details.
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
38 * xmalloc each item separately, upon free stack into idle pool array.
39 * each item is individually malloc()ed from system, imposing libmalloc
40 * overhead, and additionally we add our overhead of pointer size per item
41 * as we keep a list of pointer to free items.
44 * xmalloc Chunk that fits at least MEM_MIN_FREE (32) items in an array, but
45 * limit Chunk size to MEM_CHUNK_MAX_SIZE (256K). Chunk size is rounded up to
46 * MEM_PAGE_SIZE (4K), trying to have chunks in multiples of VM_PAGE size.
47 * Minimum Chunk size is MEM_CHUNK_SIZE (16K).
48 * A number of items fits into a single chunk, depending on item size.
49 * Maximum number of items per chunk is limited to MEM_MAX_FREE (65535).
51 * We populate Chunk with a linkedlist, each node at first word of item,
52 * and pointing at next free item. Chunk->FreeList is pointing at first
53 * free node. Thus we stuff free housekeeping into the Chunk itself, and
54 * omit pointer overhead per item.
56 * Chunks are created on demand, and new chunks are inserted into linklist
57 * of chunks so that Chunks with smaller pointer value are placed closer
58 * to the linklist head. Head is a hotspot, servicing most of requests, so
59 * slow sorting occurs and Chunks in highest memory tend to become idle
62 * event is registered that runs every 15 secs and checks reference time
63 * of each idle chunk. If a chunk is not referenced for 15 secs, it is
66 * [If mem_idle_limit is exceeded with pools, every chunk that becomes
67 * idle is immediately considered for release, unless this is the only
68 * chunk with free items in it.] (not implemented)
70 * In cachemgr output, there are new columns for chunking. Special item,
71 * Frag, is shown to estimate approximately fragmentation of chunked
72 * pools. Fragmentation is calculated by taking amount of items in use,
73 * calculating needed amount of chunks to fit all, and then comparing to
74 * actual amount of chunks in use. Frag number, in percent, is showing
75 * how many percent of chunks are in use excessively. 100% meaning that
76 * twice the needed amount of chunks are in use.
77 * "part" item shows number of chunks partially filled. This shows how
78 * badly fragmentation is spread across all chunks.
81 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
91 #define FLUSH_LIMIT 1000 /* Flush memPool counters to memMeters after flush limit calls */
92 #define MEM_MAX_MMAP_CHUNKS 2048
99 * XXX This is a boundary violation between lib and src.. would be good
100 * if it could be solved otherwise, but left for now.
102 extern time_t squid_curtime
;
105 static MemPoolMeter TheMeter
;
106 static MemPoolIterator Iterator
;
108 static int Pool_id_counter
= 0;
110 /* local prototypes */
111 static int memCompChunks(MemChunk
* const &, MemChunk
* const &);
112 static int memCompObjChunks(void * const &, MemChunk
* const &);
115 MemPools::GetInstance()
117 /* Must use this idiom, as we can be double-initialised
118 * if we are called during static initialisations.
121 Instance
= new MemPools
;
125 MemPools
* MemPools::Instance
= NULL
;
130 Iterator
.pool
= MemPools::GetInstance().pools
;
135 memPoolIterateDone(MemPoolIterator
** iter
)
137 assert(iter
!= NULL
);
138 Iterator
.pool
= NULL
;
142 MemImplementingAllocator
*
143 memPoolIterateNext(MemPoolIterator
* iter
)
145 MemImplementingAllocator
*pool
;
146 assert(iter
!= NULL
);
152 iter
->pool
= pool
->next
;
157 MemPools::setIdleLimit(size_t new_idle_limit
)
159 mem_idle_limit
= new_idle_limit
;
163 MemPools::idleLimit() const
165 return mem_idle_limit
;
170 memCompChunks(MemChunk
* const &chunkA
, MemChunk
* const &chunkB
)
172 if (chunkA
->objCache
> chunkB
->objCache
)
174 else if (chunkA
->objCache
< chunkB
->objCache
)
180 /* Compare object to chunk */
182 memCompObjChunks(void *const &obj
, MemChunk
* const &chunk
)
184 /* object is lower in memory than the chunks arena */
185 if (obj
< chunk
->objCache
)
187 /* object is within the pool */
188 if (obj
< (void *) ((char *) chunk
->objCache
+ chunk
->pool
->chunk_size
))
190 /* object is above the pool */
194 MemChunk::MemChunk(MemPool
*aPool
)
196 /* should have a pool for this too -
197 * note that this requres:
198 * allocate one chunk for the pool of chunks's first chunk
199 * allocate a chunk from that pool
200 * move the contents of one chunk into the other
201 * free the first chunk.
207 objCache
= xcalloc(1, pool
->chunk_size
);
209 void **Free
= (void **)freeList
;
211 for (int i
= 1; i
< pool
->chunk_capacity
; i
++) {
212 *Free
= (void *) ((char *) Free
+ pool
->obj_size
);
213 void **nextFree
= (void **)*Free
;
214 (void) VALGRIND_MAKE_MEM_NOACCESS(Free
, pool
->obj_size
);
217 nextFreeChunk
= pool
->nextFreeChunk
;
218 pool
->nextFreeChunk
= this;
220 memMeterAdd(pool
->getMeter().alloc
, pool
->chunk_capacity
);
221 memMeterAdd(pool
->getMeter().idle
, pool
->chunk_capacity
);
222 pool
->idle
+= pool
->chunk_capacity
;
224 lastref
= squid_curtime
;
225 pool
->allChunks
.insert(this, memCompChunks
);
228 MemPool::MemPool(const char *aLabel
, size_t aSize
) : MemImplementingAllocator(aLabel
, aSize
)
240 MemImplementingAllocator
*last_pool
;
242 assert(aLabel
!= NULL
&& aSize
);
244 setChunkSize(MEM_CHUNK_SIZE
);
247 for (last_pool
= MemPools::GetInstance().pools
; last_pool
&& last_pool
->next
;)
248 last_pool
= last_pool
->next
;
250 last_pool
->next
= this;
252 MemPools::GetInstance().pools
= this;
254 memPID
= ++Pool_id_counter
;
257 MemChunk::~MemChunk()
259 memMeterDel(pool
->getMeter().alloc
, pool
->chunk_capacity
);
260 memMeterDel(pool
->getMeter().idle
, pool
->chunk_capacity
);
261 pool
->idle
-= pool
->chunk_capacity
;
263 pool
->allChunks
.remove(this, memCompChunks
);
268 MemPool::push(void *obj
)
271 /* XXX We should figure out a sane way of avoiding having to clear
272 * all buffers. For example data buffers such as used by MemBuf do
273 * not really need to be cleared.. There was a condition based on
274 * the object size here, but such condition is not safe.
277 memset(obj
, 0, obj_size
);
281 (void) VALGRIND_MAKE_MEM_NOACCESS(obj
, obj_size
);
285 * Find a chunk with a free item.
286 * Create new chunk on demand if no chunk with frees found.
287 * Insert new chunk in front of lowest ram chunk, making it preferred in future,
288 * and resulting slow compaction towards lowest ram area.
295 /* first, try cache */
297 Free
= (void **)freeCache
;
298 (void) VALGRIND_MAKE_MEM_DEFINED(Free
, obj_size
);
303 /* then try perchunk freelist chain */
304 if (nextFreeChunk
== NULL
) {
305 /* no chunk with frees, so create new one */
308 /* now we have some in perchunk freelist chain */
309 MemChunk
*chunk
= nextFreeChunk
;
311 Free
= (void **)chunk
->freeList
;
312 chunk
->freeList
= *Free
;
314 chunk
->inuse_count
++;
315 chunk
->lastref
= squid_curtime
;
317 if (chunk
->freeList
== NULL
) {
318 /* last free in this chunk, so remove us from perchunk freelist chain */
319 nextFreeChunk
= chunk
->nextFreeChunk
;
321 (void) VALGRIND_MAKE_MEM_DEFINED(Free
, obj_size
);
325 /* just create a new chunk and place it into a good spot in the chunk chain */
327 MemPool::createChunk()
329 MemChunk
*chunk
, *newChunk
;
331 newChunk
= new MemChunk(this);
334 if (chunk
== NULL
) { /* first chunk in pool */
338 if (newChunk
->objCache
< chunk
->objCache
) {
339 /* we are lowest ram chunk, insert as first chunk */
340 newChunk
->next
= chunk
;
344 while (chunk
->next
) {
345 if (newChunk
->objCache
< chunk
->next
->objCache
) {
346 /* new chunk is in lower ram, insert here */
347 newChunk
->next
= chunk
->next
;
348 chunk
->next
= newChunk
;
353 /* we are the worst chunk in chain, add as last */
354 chunk
->next
= newChunk
;
357 /* Change the default calue of defaultIsChunked to override
358 * all pools - including those used before main() starts where
359 * MemPools::GetInstance().setDefaultPoolChunking() can be called.
361 MemPools::MemPools() : pools(NULL
), mem_idle_limit(2 * MB
),
362 poolCount (0), defaultIsChunked (!DISABLE_POOLS
&& !RUNNING_ON_VALGRIND
)
364 char *cfg
= getenv("MEMPOOLS");
366 defaultIsChunked
= atoi(cfg
);
367 #if HAVE_MALLOPT && M_MMAP_MAX
368 mallopt(M_MMAP_MAX
, MEM_MAX_MMAP_CHUNKS
);
373 MemPool::setChunkSize(size_t chunksize
)
376 size_t csize
= chunksize
;
378 if (Chunks
) /* unsafe to tamper */
381 csize
= ((csize
+ MEM_PAGE_SIZE
- 1) / MEM_PAGE_SIZE
) * MEM_PAGE_SIZE
; /* round up to page size */
382 cap
= csize
/ obj_size
;
384 if (cap
< MEM_MIN_FREE
)
386 if (cap
* obj_size
> MEM_CHUNK_MAX_SIZE
)
387 cap
= MEM_CHUNK_MAX_SIZE
/ obj_size
;
388 if (cap
> MEM_MAX_FREE
)
393 csize
= cap
* obj_size
;
394 csize
= ((csize
+ MEM_PAGE_SIZE
- 1) / MEM_PAGE_SIZE
) * MEM_PAGE_SIZE
; /* round up to page size */
395 cap
= csize
/ obj_size
;
397 chunk_capacity
= cap
;
401 MemImplementingAllocator
*
402 MemPools::create(const char *label
, size_t obj_size
)
404 return create (label
, obj_size
, defaultIsChunked
);
407 MemImplementingAllocator
*
408 MemPools::create(const char *label
, size_t obj_size
, bool const chunked
)
412 return new MemPool (label
, obj_size
);
414 return new MemMalloc (label
, obj_size
);
418 MemPools::setDefaultPoolChunking(bool const &aBool
)
420 defaultIsChunked
= aBool
;
424 * warning: we do not clean this entry from Pools assuming destruction
425 * is used at the end of the program only
429 MemChunk
*chunk
, *fchunk
;
430 MemImplementingAllocator
*find_pool
, *prev_pool
;
434 assert(inuse
== 0 && "While trying to destroy pool");
437 while ( (fchunk
= chunk
) != NULL
) {
441 /* TODO we should be doing something about the original Chunks pointer here. */
443 assert(MemPools::GetInstance().pools
!= NULL
&& "Called MemPool::~MemPool, but no pool exists!");
445 /* Pool clean, remove it from List and free */
446 for (find_pool
= MemPools::GetInstance().pools
, prev_pool
= NULL
; (find_pool
&& this != find_pool
); find_pool
= find_pool
->next
)
447 prev_pool
= find_pool
;
448 assert(find_pool
!= NULL
&& "pool to destroy not found");
451 prev_pool
->next
= next
;
453 MemPools::GetInstance().pools
= next
;
454 --MemPools::GetInstance().poolCount
;
458 MemAllocator::objectType() const
464 MemAllocator::inUseCount()
466 return getInUseCount();
470 MemImplementingAllocator::flushMeters()
476 getMeter().gb_freed
.count
+= calls
;
477 memMeterDel(getMeter().inuse
, calls
);
478 memMeterAdd(getMeter().idle
, calls
);
483 meter
.gb_saved
.count
+= calls
;
484 memMeterAdd(meter
.inuse
, calls
);
485 memMeterDel(meter
.idle
, calls
);
491 MemImplementingAllocator::flushMetersFull()
494 getMeter().gb_saved
.bytes
= getMeter().gb_saved
.count
* obj_size
;
495 getMeter().gb_freed
.bytes
= getMeter().gb_freed
.count
* obj_size
;
499 MemPoolMeter::flush()
510 * Updates all pool counters, and recreates TheMeter totals from all pools
513 MemPools::flushMeters()
515 MemImplementingAllocator
*pool
;
516 MemPoolIterator
*iter
;
520 iter
= memPoolIterate();
521 while ((pool
= memPoolIterateNext(iter
))) {
522 pool
->flushMetersFull();
523 memMeterAdd(TheMeter
.alloc
, pool
->getMeter().alloc
.level
* pool
->obj_size
);
524 memMeterAdd(TheMeter
.inuse
, pool
->getMeter().inuse
.level
* pool
->obj_size
);
525 memMeterAdd(TheMeter
.idle
, pool
->getMeter().idle
.level
* pool
->obj_size
);
526 TheMeter
.gb_saved
.count
+= pool
->getMeter().gb_saved
.count
;
527 TheMeter
.gb_freed
.count
+= pool
->getMeter().gb_freed
.count
;
528 TheMeter
.gb_saved
.bytes
+= pool
->getMeter().gb_saved
.bytes
;
529 TheMeter
.gb_freed
.bytes
+= pool
->getMeter().gb_freed
.bytes
;
531 memPoolIterateDone(&iter
);
535 MemMalloc::allocate()
538 return xcalloc(1, obj_size
);
542 MemMalloc::deallocate(void *obj
)
549 MemImplementingAllocator::alloc()
551 if (++alloc_calls
== FLUSH_LIMIT
)
558 MemImplementingAllocator::free(void *obj
)
561 (void) VALGRIND_CHECK_MEM_IS_ADDRESSABLE(obj
, obj_size
);
567 MemPool::getInUseCount()
583 MemPool::deallocate(void *obj
)
592 MemPool::convertFreeCacheToChunkFreeCache()
596 * OK, so we have to go through all the global freeCache and find the Chunk
597 * any given Free belongs to, and stuff it into that Chunk's freelist
600 while ((Free
= freeCache
) != NULL
) {
601 MemChunk
*chunk
= NULL
;
602 chunk
= const_cast<MemChunk
*>(*allChunks
.find(Free
, memCompObjChunks
));
603 assert(splayLastResult
== 0);
604 assert(chunk
->inuse_count
> 0);
605 chunk
->inuse_count
--;
606 (void) VALGRIND_MAKE_MEM_DEFINED(Free
, sizeof(void *));
607 freeCache
= *(void **)Free
; /* remove from global cache */
608 *(void **)Free
= chunk
->freeList
; /* stuff into chunks freelist */
609 (void) VALGRIND_MAKE_MEM_NOACCESS(Free
, sizeof(void *));
610 chunk
->freeList
= Free
;
611 chunk
->lastref
= squid_curtime
;
616 /* removes empty Chunks from pool */
618 MemPool::clean(time_t maxage
)
620 MemChunk
*chunk
, *freechunk
, *listTail
;
629 convertFreeCacheToChunkFreeCache();
630 /* Now we have all chunks in this pool cleared up, all free items returned to their home */
631 /* We start now checking all chunks to see if we can release any */
632 /* We start from Chunks->next, so first chunk is not released */
633 /* Recreate nextFreeChunk list from scratch */
636 while ((freechunk
= chunk
->next
) != NULL
) {
637 age
= squid_curtime
- freechunk
->lastref
;
638 freechunk
->nextFreeChunk
= NULL
;
639 if (freechunk
->inuse_count
== 0)
641 chunk
->next
= freechunk
->next
;
645 if (chunk
->next
== NULL
)
650 /* Recreate nextFreeChunk list from scratch */
651 /* Populate nextFreeChunk list in order of "most filled chunk first" */
652 /* in case of equal fill, put chunk in lower ram first */
653 /* First (create time) chunk is always on top, no matter how full */
656 nextFreeChunk
= chunk
;
657 chunk
->nextFreeChunk
= NULL
;
659 while (chunk
->next
) {
660 chunk
->next
->nextFreeChunk
= NULL
;
661 if (chunk
->next
->inuse_count
< chunk_capacity
) {
662 listTail
= nextFreeChunk
;
663 while (listTail
->nextFreeChunk
) {
664 if (chunk
->next
->inuse_count
> listTail
->nextFreeChunk
->inuse_count
)
666 if ((chunk
->next
->inuse_count
== listTail
->nextFreeChunk
->inuse_count
) &&
667 (chunk
->next
->objCache
< listTail
->nextFreeChunk
->objCache
))
669 listTail
= listTail
->nextFreeChunk
;
671 chunk
->next
->nextFreeChunk
= listTail
->nextFreeChunk
;
672 listTail
->nextFreeChunk
= chunk
->next
;
676 /* We started from 2nd chunk. If first chunk is full, remove it */
677 if (nextFreeChunk
->inuse_count
== chunk_capacity
)
678 nextFreeChunk
= nextFreeChunk
->nextFreeChunk
;
684 * Returns all cached frees to their home chunks
685 * If chunks unreferenced age is over, destroys Idle chunk
686 * Flushes meters for a pool
687 * If pool is not specified, iterates through all pools.
688 * When used for all pools, if new_idle_limit is above -1, new
689 * idle memory limit is set before Cleanup. This allows to shrink
690 * memPool memory usage to specified minimum.
693 MemPools::clean(time_t maxage
)
695 MemImplementingAllocator
*pool
;
696 MemPoolIterator
*iter
;
700 if (TheMeter
.idle
.level
> mem_idle_limit
)
703 iter
= memPoolIterate();
704 while ((pool
= memPoolIterateNext(iter
)))
705 if (pool
->idleTrigger(shift
))
707 memPoolIterateDone(&iter
);
711 MemPool::idleTrigger(int shift
) const
713 return getMeter().idle
.level
> (chunk_capacity
<< shift
);
716 /* Persistent Pool stats. for GlobalStats accumulation */
717 static MemPoolStats pp_stats
;
720 * Update MemPoolStats struct for single pool
723 MemPool::getStats(MemPoolStats
* stats
)
727 int chunks_partial
= 0;
729 if (stats
!= &pp_stats
) /* need skip memset for GlobalStats accumulation */
731 memset(stats
, 0, sizeof(MemPoolStats
));
733 clean((time_t) 555555); /* don't want to get chunks released before reporting */
736 stats
->label
= objectType();
737 stats
->meter
= &getMeter();
738 stats
->obj_size
= obj_size
;
739 stats
->chunk_capacity
= chunk_capacity
;
741 /* gather stats for each Chunk */
744 if (chunk
->inuse_count
== 0)
746 else if (chunk
->inuse_count
< chunk_capacity
)
751 stats
->chunks_alloc
+= chunkCount
;
752 stats
->chunks_inuse
+= chunkCount
- chunks_free
;
753 stats
->chunks_partial
+= chunks_partial
;
754 stats
->chunks_free
+= chunks_free
;
756 stats
->items_alloc
+= getMeter().alloc
.level
;
757 stats
->items_inuse
+= getMeter().inuse
.level
;
758 stats
->items_idle
+= getMeter().idle
.level
;
760 stats
->overhead
+= sizeof(MemPool
) + chunkCount
* sizeof(MemChunk
) + strlen(objectType()) + 1;
762 return getMeter().inuse
.level
;
765 /* TODO extract common logic to MemAllocate */
767 MemMalloc::getStats(MemPoolStats
* stats
)
769 if (stats
!= &pp_stats
) /* need skip memset for GlobalStats accumulation */
771 memset(stats
, 0, sizeof(MemPoolStats
));
774 stats
->label
= objectType();
775 stats
->meter
= &getMeter();
776 stats
->obj_size
= obj_size
;
777 stats
->chunk_capacity
= 0;
779 stats
->chunks_alloc
+= 0;
780 stats
->chunks_inuse
+= 0;
781 stats
->chunks_partial
+= 0;
782 stats
->chunks_free
+= 0;
784 stats
->items_alloc
+= getMeter().alloc
.level
;
785 stats
->items_inuse
+= getMeter().inuse
.level
;
786 stats
->items_idle
+= getMeter().idle
.level
;
788 stats
->overhead
+= sizeof(MemMalloc
) + strlen(objectType()) + 1;
790 return getMeter().inuse
.level
;
794 MemMalloc::getInUseCount()
800 * Totals statistics is returned
803 memPoolGetGlobalStats(MemPoolGlobalStats
* stats
)
807 MemPoolIterator
*iter
;
809 memset(stats
, 0, sizeof(MemPoolGlobalStats
));
810 memset(&pp_stats
, 0, sizeof(MemPoolStats
));
812 MemPools::GetInstance().flushMeters(); /* recreate TheMeter */
814 /* gather all stats for Totals */
815 iter
= memPoolIterate();
816 while ((pool
= memPoolIterateNext(iter
))) {
817 if (pool
->getStats(&pp_stats
) > 0)
820 memPoolIterateDone(&iter
);
822 stats
->TheMeter
= &TheMeter
;
824 stats
->tot_pools_alloc
= MemPools::GetInstance().poolCount
;
825 stats
->tot_pools_inuse
= pools_inuse
;
826 stats
->tot_pools_mempid
= Pool_id_counter
;
828 stats
->tot_chunks_alloc
= pp_stats
.chunks_alloc
;
829 stats
->tot_chunks_inuse
= pp_stats
.chunks_inuse
;
830 stats
->tot_chunks_partial
= pp_stats
.chunks_partial
;
831 stats
->tot_chunks_free
= pp_stats
.chunks_free
;
832 stats
->tot_items_alloc
= pp_stats
.items_alloc
;
833 stats
->tot_items_inuse
= pp_stats
.items_inuse
;
834 stats
->tot_items_idle
= pp_stats
.items_idle
;
836 stats
->tot_overhead
+= pp_stats
.overhead
+ MemPools::GetInstance().poolCount
* sizeof(MemPool
*);
837 stats
->mem_idle_limit
= MemPools::GetInstance().mem_idle_limit
;
842 MemAllocator::MemAllocator(char const *aLabel
) : doZeroOnPush(true), label(aLabel
)
846 size_t MemAllocator::RoundedSize(size_t s
)
848 return ((s
+ sizeof(void*) - 1) / sizeof(void*)) * sizeof(void*);
851 MemMalloc::MemMalloc(char const *label
, size_t aSize
) : MemImplementingAllocator(label
, aSize
) { inuse
= 0; }
854 MemMalloc::idleTrigger(int shift
) const
860 MemMalloc::clean(time_t maxage
)
865 memPoolInUseCount(MemAllocator
* pool
)
867 return pool
->inUseCount();
871 memPoolsTotalAllocated(void)
873 MemPoolGlobalStats stats
;
874 memPoolGetGlobalStats(&stats
);
875 return stats
.TheMeter
->alloc
.level
;
879 MemAllocatorProxy::alloc()
881 return getAllocator()->alloc();
885 MemAllocatorProxy::free(void *address
)
887 getAllocator()->free(address
);
888 /* TODO: check for empty, and if so, if the default type has altered,
894 MemAllocatorProxy::getAllocator() const
897 theAllocator
= MemPools::GetInstance().create(objectType(), size
);
902 MemAllocatorProxy::inUseCount() const
907 return memPoolInUseCount(theAllocator
);
911 MemAllocatorProxy::objectSize() const
917 MemAllocatorProxy::objectType() const
923 MemAllocatorProxy::getMeter() const
925 return getAllocator()->getMeter();
929 MemAllocatorProxy::getStats(MemPoolStats
* stats
)
931 return getAllocator()->getStats(stats
);
934 MemImplementingAllocator::MemImplementingAllocator(char const *aLabel
, size_t aSize
) : MemAllocator(aLabel
),
938 obj_size(RoundedSize(aSize
))
943 MemAllocator::zeroOnPush(bool doIt
)
949 MemImplementingAllocator::getMeter() const
955 MemImplementingAllocator::getMeter()
961 MemImplementingAllocator::objectSize() const