A size-based allocator that caches blocks for quicker access, but if the pool is exhausted it will use the heap. More...
#include <Dynamic_Cached_Allocator_With_Overflow_T.h>
Public Member Functions | |
Dynamic_Cached_Allocator_With_Overflow (size_t n_chunks, size_t chunk_size) | |
~Dynamic_Cached_Allocator_With_Overflow () | |
Clear things up. | |
void * | malloc (size_t nbytes=0) |
virtual void * | calloc (size_t, char= '\0') |
virtual void * | calloc (size_t, size_t, char= '\0') |
void | free (void *ptr) |
Return a chunk of memory back to free list cache. | |
size_t | pool_depth () |
Return the number of chunks available in the cache. | |
size_t | available () |
Public Attributes | |
ACE_Atomic_Op < ACE_Thread_Mutex, unsigned long > | allocs_from_heap_ |
number of allocations from the heap. | |
ACE_Atomic_Op < ACE_Thread_Mutex, unsigned long > | allocs_from_pool_ |
number of allocations from the pool. | |
ACE_Atomic_Op < ACE_Thread_Mutex, unsigned long > | frees_to_heap_ |
number of frees returned to the heap | |
ACE_Atomic_Op < ACE_Thread_Mutex, unsigned long > | frees_to_pool_ |
number of frees returned to the pool | |
Private Attributes | |
unsigned char * | begin_ |
unsigned char * | end_ |
The end of the pool. | |
ACE_Locked_Free_List < ACE_Cached_Mem_Pool_Node < char >, ACE_LOCK > | free_list_ |
size_t | chunk_size_ |
Remember the size of our chunks. |
A size-based allocator that caches blocks for quicker access, but if the pool is exhausted it will use the heap.
This class enables caching of dynamically allocated, fixed-size chunks. Notice that the chunk_size
must be greater than or equal to sizeof (void*)
for this to work properly.
This class can be configured flexibly with different types of ACE_LOCK strategies that support the ACE_Thread_Mutex and ACE_Process_Mutex constructor API.
Definition at line 44 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::Dynamic_Cached_Allocator_With_Overflow | ( | size_t | n_chunks, | |
size_t | chunk_size | |||
) | [inline] |
Create a cached memory pool with n_chunks chunks each with chunk_size size.
Definition at line 48 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
References ACE_Locked_Free_List< T, ACE_LOCK >::add(), OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::begin_, c, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::chunk_size_, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::end_, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free_list_, ACE_Allocator::instance(), and ACE_Allocator::malloc().
00049 : allocs_from_heap_(0), 00050 allocs_from_pool_(0), 00051 frees_to_heap_(0), 00052 frees_to_pool_(0), 00053 free_list_(ACE_PURE_FREE_LIST) 00054 { 00055 chunk_size_ = ACE_MALLOC_ROUNDUP(chunk_size, ACE_MALLOC_ALIGN); 00056 begin_ = static_cast<unsigned char*> (ACE_Allocator::instance()->malloc(n_chunks * chunk_size_)); 00057 // Remember end of the pool. 00058 end_ = begin_ + n_chunks * chunk_size_; 00059 00060 // Put into free list using placement contructor, no real memory 00061 // allocation in the <new> below. 00062 for (size_t c = 0; 00063 c < n_chunks; 00064 c++) { 00065 void* placement = begin_ + c * chunk_size_; 00066 00067 this->free_list_.add(new(placement) ACE_Cached_Mem_Pool_Node<char>); 00068 } 00069 }
OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::~Dynamic_Cached_Allocator_With_Overflow | ( | ) | [inline] |
Clear things up.
Definition at line 72 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
References OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::begin_, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::chunk_size_, ACE_Allocator::free(), and ACE_Allocator::instance().
00072 { 00073 ACE_Allocator::instance()->free(begin_); 00074 begin_ = 0; 00075 chunk_size_ = 0; 00076 }
size_t OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::available | ( | void | ) | [inline] |
How many chunks are available at this time.
Definition at line 211 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
References OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free_list_, and ACE_Locked_Free_List< T, ACE_LOCK >::size().
Referenced by OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free(), and OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::malloc().
00211 { 00212 return free_list_.size(); 00213 };
virtual void* OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::calloc | ( | size_t | , | |
size_t | , | |||
char | = '\0' | |||
) | [inline, virtual] |
This method is a no-op and just returns 0 since the free list only works with fixed sized entities.
Reimplemented from ACE_New_Allocator.
Definition at line 143 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
virtual void* OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::calloc | ( | size_t | , | |
char | = '\0' | |||
) | [inline, virtual] |
Get a chunk of memory from free list cache, giving them initial_value. Note that nbytes is only checked to make sure that it's less or equal to chunk_size, and is otherwise ignored since calloc() always returns a pointer to an item of chunk_size.
Reimplemented from ACE_New_Allocator.
Definition at line 136 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
void OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free | ( | void * | ptr | ) | [inline, virtual] |
Return a chunk of memory back to free list cache.
Reimplemented from ACE_New_Allocator.
Definition at line 150 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
References ACE_Locked_Free_List< T, ACE_LOCK >::add(), OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::allocs_from_heap_, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::allocs_from_pool_, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::available(), OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::begin_, OpenDDS::DCPS::DCPS_debug_level, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::end_, ACE_Allocator::free(), OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free_list_, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::frees_to_heap_, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::frees_to_pool_, ACE_Allocator::instance(), LM_DEBUG, LM_ERROR, and ACE_Atomic_Op< ACE_Thread_Mutex, unsigned long >::value().
00150 { 00151 unsigned char* tmp = static_cast<unsigned char*> (ptr); 00152 if (tmp < begin_ || 00153 tmp >= end_) { 00154 ACE_Allocator::instance()->free(tmp); 00155 frees_to_heap_ ++; 00156 00157 if (frees_to_heap_.value() > allocs_from_heap_.value()) { 00158 ACE_ERROR((LM_ERROR, 00159 "(%P|%t) ERROR: Dynamic_Cached_Allocator_With_Overflow::free %x" 00160 " more deletes %d than allocs %d to the heap\n", 00161 this, 00162 this->frees_to_heap_.value(), 00163 this->allocs_from_heap_.value())); 00164 } 00165 00166 if (DCPS_debug_level >= 6) { 00167 if (frees_to_heap_.value() % 500 == 0) { 00168 ACE_DEBUG((LM_DEBUG, 00169 "(%P|%t) Dynamic_Cached_Allocator_With_Overflow::free %x" 00170 " %d heap allocs with %d oustanding\n", 00171 this, this->allocs_from_heap_.value(), 00172 this->allocs_from_heap_.value() - this->frees_to_heap_.value())); 00173 } 00174 } 00175 00176 return; 00177 00178 } else if (ptr != 0) { 00179 this->frees_to_pool_ ++; 00180 00181 if (frees_to_pool_.value() > allocs_from_pool_.value()) { 00182 ACE_ERROR((LM_ERROR, 00183 "(%P|%t) ERROR: Dynamic_Cached_Allocator_With_Overflow::free %x" 00184 " more deletes %d than allocs %d from the pool\n", 00185 this, 00186 this->frees_to_pool_.value(), 00187 this->allocs_from_pool_.value())); 00188 } 00189 00190 this->free_list_.add((ACE_Cached_Mem_Pool_Node<char> *) ptr) ; 00191 00192 if (DCPS_debug_level >= 6) 00193 if (this->available() % 500 == 0) 00194 ACE_DEBUG((LM_DEBUG, 00195 "(%P|%t) Dynamic_Cached_Allocator_With_Overflow::malloc %x" 00196 " %d pool allocs %d pool frees with %d available\n", 00197 this, this->allocs_from_pool_.value(), this->frees_to_pool_.value(), 00198 this->available())); 00199 } 00200 }
void* OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::malloc | ( | size_t | nbytes = 0 |
) | [inline, virtual] |
Get a chunk of memory from free list cache. Note that nbytes is only checked to make sure that it's less or equal to chunk_size, and is otherwise ignored since malloc() always returns a pointer to an item of chunk_size size.
Reimplemented from ACE_New_Allocator.
Definition at line 84 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
References ACE_Cached_Mem_Pool_Node< T >::addr(), OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::allocs_from_heap_, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::allocs_from_pool_, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::available(), OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::chunk_size_, OpenDDS::DCPS::DCPS_debug_level, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free_list_, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::frees_to_heap_, OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::frees_to_pool_, ACE_Allocator::instance(), LM_DEBUG, ACE_Allocator::malloc(), ACE_Locked_Free_List< T, ACE_LOCK >::remove(), and ACE_Atomic_Op< ACE_Thread_Mutex, unsigned long >::value().
00084 { 00085 // Check if size requested fits within pre-determined size. 00086 if (nbytes > chunk_size_) 00087 return 0; 00088 00089 // addr() call is really not absolutely necessary because of the way 00090 // ACE_Cached_Mem_Pool_Node's internal structure arranged. 00091 void* rtn = this->free_list_.remove()->addr(); 00092 00093 if (0 == rtn) { 00094 rtn = ACE_Allocator::instance()->malloc(chunk_size_); 00095 allocs_from_heap_++; 00096 00097 if (DCPS_debug_level >= 2) { 00098 if (allocs_from_heap_ == 1 && DCPS_debug_level >= 2) 00099 ACE_DEBUG((LM_DEBUG, 00100 "(%P|%t) Dynamic_Cached_Allocator_With_Overflow::malloc %x" 00101 " %d heap allocs with %d outstanding\n", 00102 this, this->allocs_from_heap_.value(), 00103 this->allocs_from_heap_.value() - this->frees_to_heap_.value())); 00104 00105 if (DCPS_debug_level >= 6) 00106 if (allocs_from_heap_.value() % 500 == 0) 00107 ACE_DEBUG((LM_DEBUG, 00108 "(%P|%t) Dynamic_Cached_Allocator_With_Overflow::malloc %x" 00109 " %d heap allocs with %d outstanding\n", 00110 this, this->allocs_from_heap_.value(), 00111 this->allocs_from_heap_.value() - this->frees_to_heap_.value())); 00112 } 00113 00114 } else { 00115 allocs_from_pool_++; 00116 00117 if (DCPS_debug_level >= 6) 00118 if (allocs_from_pool_.value() % 500 == 0) 00119 ACE_DEBUG((LM_DEBUG, 00120 "(%P|%t) Dynamic_Cached_Allocator_With_Overflow::malloc %x" 00121 " %d pool allocs %d pool free with %d available\n", 00122 this, this->allocs_from_pool_.value(), 00123 this->frees_to_pool_.value(), 00124 this->available())); 00125 } 00126 00127 return rtn; 00128 }
size_t OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::pool_depth | ( | ) | [inline] |
Return the number of chunks available in the cache.
Definition at line 203 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
References OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free_list_, and ACE_Locked_Free_List< T, ACE_LOCK >::size().
00203 { 00204 return this->free_list_.size() ; 00205 }
ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::allocs_from_heap_ |
number of allocations from the heap.
Definition at line 213 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free(), and OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::malloc().
ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::allocs_from_pool_ |
number of allocations from the pool.
Definition at line 218 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free(), and OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::malloc().
unsigned char* OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::begin_ [private] |
Remember how we allocate the memory in the first place so we can clear things up later.
Definition at line 226 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::Dynamic_Cached_Allocator_With_Overflow(), OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free(), and OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::~Dynamic_Cached_Allocator_With_Overflow().
size_t OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::chunk_size_ [private] |
Remember the size of our chunks.
Definition at line 237 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::Dynamic_Cached_Allocator_With_Overflow(), OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::malloc(), and OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::~Dynamic_Cached_Allocator_With_Overflow().
unsigned char* OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::end_ [private] |
The end of the pool.
Definition at line 228 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::Dynamic_Cached_Allocator_With_Overflow(), and OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free().
ACE_Locked_Free_List<ACE_Cached_Mem_Pool_Node<char>, ACE_LOCK> OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free_list_ [private] |
Maintain a cached memory free list. We use char
as template parameter, although sizeof(char) is usually less than sizeof(void*). Really important is that chunk_size must be greater or equal to sizeof(void*).
Definition at line 234 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::available(), OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::Dynamic_Cached_Allocator_With_Overflow(), OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free(), OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::malloc(), and OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::pool_depth().
ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::frees_to_heap_ |
number of frees returned to the heap
Definition at line 220 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free(), and OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::malloc().
ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::frees_to_pool_ |
number of frees returned to the pool
Definition at line 222 of file Dynamic_Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::free(), and OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::malloc().