OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK > Class Template Reference

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>

Inheritance diagram for OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >:
Inheritance graph
[legend]
Collaboration diagram for OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >:
Collaboration graph
[legend]

List of all members.

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.

Detailed Description

template<class ACE_LOCK>
class OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >

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.


Constructor & Destructor Documentation

template<class ACE_LOCK >
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   }

Here is the call graph for this function:


Member Function Documentation

template<class ACE_LOCK >
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   };

Here is the call graph for this function:

Here is the caller graph for this function:

template<class ACE_LOCK >
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.

00145                                                         {
00146     ACE_NOTSUP_RETURN(0);
00147   }

template<class ACE_LOCK >
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.

00137                                                         {
00138     ACE_NOTSUP_RETURN(0);
00139   }

template<class ACE_LOCK >
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   }

Here is the call graph for this function:

template<class ACE_LOCK >
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   }

Here is the call graph for this function:

template<class ACE_LOCK >
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   }

Here is the call graph for this function:


Member Data Documentation

template<class ACE_LOCK >
unsigned char* OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::begin_ [private]
template<class ACE_LOCK >
size_t OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::chunk_size_ [private]
template<class ACE_LOCK >
unsigned char* OpenDDS::DCPS::Dynamic_Cached_Allocator_With_Overflow< ACE_LOCK >::end_ [private]

The documentation for this class was generated from the following file:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1