A fixed-size allocator that caches items for quicker access but if the pool is exhausted it will use the heap. More...
#include <Cached_Allocator_With_Overflow_T.h>
Public Member Functions | |
Cached_Allocator_With_Overflow (size_t n_chunks) | |
~Cached_Allocator_With_Overflow () | |
Clear things up. | |
void * | malloc (size_t nbytes=sizeof(T)) |
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 | available () |
Public Attributes | |
ACE_Atomic_Op < ACE_Thread_Mutex, unsigned long > | allocs_from_heap_ |
ACE_Atomic_Op < ACE_Thread_Mutex, unsigned long > | allocs_from_pool_ |
ACE_Atomic_Op < ACE_Thread_Mutex, unsigned long > | frees_to_heap_ |
ACE_Atomic_Op < ACE_Thread_Mutex, unsigned long > | frees_to_pool_ |
Private Attributes | |
unsigned char * | begin_ |
unsigned char * | end_ |
The end of the pool. | |
ACE_Locked_Free_List < ACE_Cached_Mem_Pool_Node< T > , ACE_LOCK > | free_list_ |
Maintain a cached memory free list. |
A fixed-size allocator that caches items for quicker access but if the pool is exhausted it will use the heap.
This class enables caching of dynamically allocated, fixed-sized classes. Notice that the sizeof (TYPE)
must be greater than or equal to sizeof (void*)
for this to work properly. If the free list is empty then memory is allocated from the heap. This way the allocations will not fail but may be slower.
Definition at line 45 of file Cached_Allocator_With_Overflow_T.h.
OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, ACE_LOCK >::Cached_Allocator_With_Overflow | ( | size_t | n_chunks | ) | [inline] |
Create a cached memory pool with n_chunks chunks each with sizeof (TYPE) size.
Definition at line 49 of file Cached_Allocator_With_Overflow_T.h.
00050 : allocs_from_heap_(0), 00051 allocs_from_pool_(0), 00052 frees_to_heap_(0), 00053 frees_to_pool_(0), 00054 free_list_(ACE_PURE_FREE_LIST) { 00055 // To maintain alignment requirements, make sure that each element 00056 // inserted into the free list is aligned properly for the platform. 00057 // Since the memory is allocated as a char[], the compiler won't help. 00058 // To make sure enough room is allocated, round up the size so that 00059 // each element starts aligned. 00060 // 00061 // NOTE - this would probably be easier by defining begin_ as a pointer 00062 // to T and allocating an array of them (the compiler would probably 00063 // take care of the alignment for us), but then the ACE_NEW below would 00064 // require a default constructor on T - a requirement that is not in 00065 // previous versions of ACE 00066 size_t chunk_size = sizeof(T); 00067 chunk_size = ACE_MALLOC_ROUNDUP(chunk_size, ACE_MALLOC_ALIGN); 00068 begin_ = static_cast<unsigned char*> (ACE_Allocator::instance()->malloc(n_chunks * chunk_size)); 00069 00070 // Remember end of the pool. 00071 end_ = begin_ + n_chunks * chunk_size; 00072 00073 // Put into free list using placement contructor, no real memory 00074 // allocation in the <new> below. 00075 for (size_t c = 0; c < n_chunks; c++) { 00076 void* placement = begin_ + c * chunk_size; 00077 this->free_list_.add(new(placement) ACE_Cached_Mem_Pool_Node<T>); 00078 } 00079 }
OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, ACE_LOCK >::~Cached_Allocator_With_Overflow | ( | ) | [inline] |
Clear things up.
Definition at line 82 of file Cached_Allocator_With_Overflow_T.h.
00082 { 00083 ACE_Allocator::instance()->free(begin_); 00084 }
size_t OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, ACE_LOCK >::available | ( | void | ) | [inline] |
How many chunks are available at this time.
Definition at line 211 of file Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Cached_Allocator_With_Overflow< ACE_Message_Block, RECEIVE_SYNCH >::free(), and OpenDDS::DCPS::Cached_Allocator_With_Overflow< ACE_Message_Block, RECEIVE_SYNCH >::malloc().
00211 { 00212 return free_list_.size(); 00213 };
virtual void* OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, 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 149 of file Cached_Allocator_With_Overflow_T.h.
virtual void* OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, 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 sizeof T, and is otherwise ignored since calloc() always returns a pointer to an item of sizeof (T).
Reimplemented from ACE_New_Allocator.
Definition at line 142 of file Cached_Allocator_With_Overflow_T.h.
void OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, 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 156 of file Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::TransportReceiveStrategy< TH, DSH >::handle_dds_input(), and OpenDDS::DCPS::WriteDataContainer::release_buffer().
00156 { 00157 unsigned char* tmp = static_cast<unsigned char*>(ptr); 00158 if (tmp < begin_ || 00159 tmp >= end_) { 00160 ACE_Allocator::instance()->free(tmp); 00161 frees_to_heap_++; 00162 00163 if (frees_to_heap_ > allocs_from_heap_.value()) { 00164 ACE_ERROR((LM_ERROR, 00165 "(%P|%t) ERROR:Cached_Allocator_With_Overflow::free %@" 00166 " more deletes %Lu than allocs %Lu to the heap\n", 00167 this, 00168 this->frees_to_heap_.value(), 00169 this->allocs_from_heap_.value())); 00170 } 00171 00172 if (DCPS_debug_level >= 6) { 00173 if (frees_to_heap_.value() % 500 == 0) { 00174 ACE_DEBUG((LM_DEBUG, 00175 "(%P|%t) Cached_Allocator_With_Overflow::free %@" 00176 " %Lu heap allocs with %Lu outstanding\n", 00177 this, this->allocs_from_heap_.value(), 00178 this->allocs_from_heap_.value() - this->frees_to_heap_.value())); 00179 } 00180 } 00181 00182 } else if (ptr != 0) { 00183 frees_to_pool_ ++; 00184 00185 if (frees_to_pool_ > allocs_from_pool_.value()) { 00186 ACE_ERROR((LM_ERROR, 00187 "(%P|%t) ERROR: Cached_Allocator_With_Overflow::free %@" 00188 " more deletes %Lu than allocs %Lu from the pool ptr=%@ begin_=%@ end_=%@\n", 00189 this, 00190 this->frees_to_pool_.value(), 00191 this->allocs_from_pool_.value(), ptr, begin_, end_)); 00192 } 00193 00194 this->free_list_.add((ACE_Cached_Mem_Pool_Node<T> *) ptr) ; 00195 00196 if (DCPS_debug_level >= 6) 00197 if (this->available() % 500 == 0) 00198 ACE_DEBUG((LM_DEBUG, 00199 "(%P|%t) Cached_Allocator_With_Overflow::malloc %@" 00200 " %Lu pool allocs %Lu pool free with %Lu available\n", 00201 this, this->allocs_from_pool_.value(), 00202 this->frees_to_pool_.value(), 00203 this->available())); 00204 } 00205 }
void* OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, ACE_LOCK >::malloc | ( | size_t | nbytes = sizeof(T) |
) | [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 sizeof T, and is otherwise ignored since malloc()
always returns a pointer to an item of sizeof (T).
Reimplemented from ACE_New_Allocator.
Definition at line 91 of file Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::TransportQueueElement::clone_mb(), OpenDDS::DCPS::WriteDataContainer::copy_and_prepend(), OpenDDS::DCPS::TransportReceiveStrategy< TH, DSH >::handle_dds_input(), OpenDDS::DCPS::WriteDataContainer::obtain_buffer(), and OpenDDS::DCPS::WriteDataContainer::obtain_buffer_for_control().
00091 { 00092 // Check if size requested fits within pre-determined size. 00093 if (nbytes > sizeof(T)) 00094 return 0; 00095 00096 // addr() call is really not absolutely necessary because of the way 00097 // ACE_Cached_Mem_Pool_Node's internal structure arranged. 00098 void* rtn = this->free_list_.remove()->addr(); 00099 00100 if (0 == rtn) { 00101 rtn = ACE_Allocator::instance()->malloc(sizeof(T)); 00102 allocs_from_heap_++; 00103 00104 if (DCPS_debug_level >= 2) { 00105 if (allocs_from_heap_ == 1 && DCPS_debug_level >= 2) 00106 ACE_DEBUG((LM_DEBUG, 00107 "(%P|%t) Cached_Allocator_With_Overflow::malloc %@" 00108 " %Lu heap allocs with %Lu outstanding\n", 00109 this, this->allocs_from_heap_.value(), 00110 this->allocs_from_heap_.value() - this->frees_to_heap_.value())); 00111 00112 if (DCPS_debug_level >= 6) 00113 if (allocs_from_heap_.value() % 500 == 0) 00114 ACE_DEBUG((LM_DEBUG, 00115 "(%P|%t) Cached_Allocator_With_Overflow::malloc %@" 00116 " %Lu heap allocs with %Lu outstanding\n", 00117 this, this->allocs_from_heap_.value(), 00118 this->allocs_from_heap_.value() - this->frees_to_heap_.value())); 00119 } 00120 00121 } else { 00122 allocs_from_pool_++; 00123 00124 if (DCPS_debug_level >= 6) 00125 if (allocs_from_pool_.value() % 500 == 0) 00126 ACE_DEBUG((LM_DEBUG, 00127 "(%P|%t) Cached_Allocator_With_Overflow::malloc %@" 00128 " %Lu pool allocs %Lu pool frees with %Lu available\n", 00129 this, this->allocs_from_pool_.value(), this->frees_to_pool_.value(), 00130 this->available())); 00131 } 00132 00133 return rtn; 00134 }
ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, ACE_LOCK >::allocs_from_heap_ |
ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, ACE_LOCK >::allocs_from_pool_ |
unsigned char* OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, ACE_LOCK >::begin_ [private] |
Remember how we allocate the memory in the first place so we can clear things up later.
Definition at line 223 of file Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Cached_Allocator_With_Overflow< ACE_Message_Block, RECEIVE_SYNCH >::Cached_Allocator_With_Overflow(), OpenDDS::DCPS::Cached_Allocator_With_Overflow< ACE_Message_Block, RECEIVE_SYNCH >::free(), and OpenDDS::DCPS::Cached_Allocator_With_Overflow< ACE_Message_Block, RECEIVE_SYNCH >::~Cached_Allocator_With_Overflow().
unsigned char* OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, ACE_LOCK >::end_ [private] |
The end of the pool.
Definition at line 225 of file Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Cached_Allocator_With_Overflow< ACE_Message_Block, RECEIVE_SYNCH >::Cached_Allocator_With_Overflow(), and OpenDDS::DCPS::Cached_Allocator_With_Overflow< ACE_Message_Block, RECEIVE_SYNCH >::free().
ACE_Locked_Free_List<ACE_Cached_Mem_Pool_Node<T>, ACE_LOCK> OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, ACE_LOCK >::free_list_ [private] |
Maintain a cached memory free list.
Definition at line 228 of file Cached_Allocator_With_Overflow_T.h.
Referenced by OpenDDS::DCPS::Cached_Allocator_With_Overflow< ACE_Message_Block, RECEIVE_SYNCH >::available(), OpenDDS::DCPS::Cached_Allocator_With_Overflow< ACE_Message_Block, RECEIVE_SYNCH >::Cached_Allocator_With_Overflow(), OpenDDS::DCPS::Cached_Allocator_With_Overflow< ACE_Message_Block, RECEIVE_SYNCH >::free(), and OpenDDS::DCPS::Cached_Allocator_With_Overflow< ACE_Message_Block, RECEIVE_SYNCH >::malloc().
ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, ACE_LOCK >::frees_to_heap_ |
ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> OpenDDS::DCPS::Cached_Allocator_With_Overflow< T, ACE_LOCK >::frees_to_pool_ |