00001
00002
00003
00004
00005
00006
00007
00008 #ifndef DYNAMIC_CACHED_ALLOCATOR_WITH_OVERFLOW_T_H
00009 #define DYNAMIC_CACHED_ALLOCATOR_WITH_OVERFLOW_T_H
00010
00011 #include "debug.h"
00012 #include "ace/Malloc_Allocator.h"
00013 #include "ace/Malloc_T.h"
00014 #include "ace/Free_List.h"
00015 #include "ace/Guard_T.h"
00016
00017 #include "PoolAllocationBase.h"
00018
00019 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00020 # pragma once
00021 #endif
00022
00023 namespace OpenDDS {
00024 namespace DCPS {
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 template <class ACE_LOCK>
00042 class Dynamic_Cached_Allocator_With_Overflow : public ACE_New_Allocator, public PoolAllocationBase {
00043 public:
00044
00045
00046 Dynamic_Cached_Allocator_With_Overflow(size_t n_chunks, size_t chunk_size)
00047 : allocs_from_heap_(0),
00048 allocs_from_pool_(0),
00049 frees_to_heap_(0),
00050 frees_to_pool_(0),
00051 free_list_(ACE_PURE_FREE_LIST)
00052 {
00053 chunk_size_ = ACE_MALLOC_ROUNDUP(chunk_size, ACE_MALLOC_ALIGN);
00054 begin_ = static_cast<unsigned char*> (ACE_Allocator::instance()->malloc(n_chunks * chunk_size_));
00055
00056 end_ = begin_ + n_chunks * chunk_size_;
00057
00058
00059
00060 for (size_t c = 0;
00061 c < n_chunks;
00062 c++) {
00063 void* placement = begin_ + c * chunk_size_;
00064
00065 this->free_list_.add(new(placement) ACE_Cached_Mem_Pool_Node<char>);
00066 }
00067 }
00068
00069
00070 ~Dynamic_Cached_Allocator_With_Overflow() {
00071 ACE_Allocator::instance()->free(begin_);
00072 begin_ = 0;
00073 chunk_size_ = 0;
00074 }
00075
00076
00077
00078
00079
00080
00081
00082 void *malloc(size_t nbytes = 0) {
00083
00084 if (nbytes > chunk_size_)
00085 return 0;
00086
00087
00088
00089 void* rtn = this->free_list_.remove()->addr();
00090
00091 if (0 == rtn) {
00092 rtn = ACE_Allocator::instance()->malloc(chunk_size_);
00093 allocs_from_heap_++;
00094
00095 if (DCPS_debug_level >= 2) {
00096 if (allocs_from_heap_ == 1 && DCPS_debug_level >= 2)
00097 ACE_DEBUG((LM_DEBUG,
00098 "(%P|%t) Dynamic_Cached_Allocator_With_Overflow::malloc %x"
00099 " %d heap allocs with %d outstanding\n",
00100 this, this->allocs_from_heap_.value(),
00101 this->allocs_from_heap_.value() - this->frees_to_heap_.value()));
00102
00103 if (DCPS_debug_level >= 6)
00104 if (allocs_from_heap_.value() % 500 == 0)
00105 ACE_DEBUG((LM_DEBUG,
00106 "(%P|%t) Dynamic_Cached_Allocator_With_Overflow::malloc %x"
00107 " %d heap allocs with %d outstanding\n",
00108 this, this->allocs_from_heap_.value(),
00109 this->allocs_from_heap_.value() - this->frees_to_heap_.value()));
00110 }
00111
00112 } else {
00113 allocs_from_pool_++;
00114
00115 if (DCPS_debug_level >= 6)
00116 if (allocs_from_pool_.value() % 500 == 0)
00117 ACE_DEBUG((LM_DEBUG,
00118 "(%P|%t) Dynamic_Cached_Allocator_With_Overflow::malloc %x"
00119 " %d pool allocs %d pool free with %d available\n",
00120 this, this->allocs_from_pool_.value(),
00121 this->frees_to_pool_.value(),
00122 this->available()));
00123 }
00124
00125 return rtn;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134 virtual void *calloc(size_t ,
00135 char = '\0') {
00136 ACE_NOTSUP_RETURN(0);
00137 }
00138
00139
00140
00141 virtual void *calloc(size_t ,
00142 size_t ,
00143 char = '\0') {
00144 ACE_NOTSUP_RETURN(0);
00145 }
00146
00147
00148 void free(void * ptr) {
00149 unsigned char* tmp = static_cast<unsigned char*> (ptr);
00150 if (tmp < begin_ ||
00151 tmp >= end_) {
00152 ACE_Allocator::instance()->free(tmp);
00153 frees_to_heap_ ++;
00154
00155 if (frees_to_heap_.value() > allocs_from_heap_.value()) {
00156 ACE_ERROR((LM_ERROR,
00157 "(%P|%t) ERROR: Dynamic_Cached_Allocator_With_Overflow::free %x"
00158 " more deletes %d than allocs %d to the heap\n",
00159 this,
00160 this->frees_to_heap_.value(),
00161 this->allocs_from_heap_.value()));
00162 }
00163
00164 if (DCPS_debug_level >= 6) {
00165 if (frees_to_heap_.value() % 500 == 0) {
00166 ACE_DEBUG((LM_DEBUG,
00167 "(%P|%t) Dynamic_Cached_Allocator_With_Overflow::free %x"
00168 " %d heap allocs with %d oustanding\n",
00169 this, this->allocs_from_heap_.value(),
00170 this->allocs_from_heap_.value() - this->frees_to_heap_.value()));
00171 }
00172 }
00173
00174 return;
00175
00176 } else if (ptr != 0) {
00177 this->frees_to_pool_ ++;
00178
00179 if (frees_to_pool_.value() > allocs_from_pool_.value()) {
00180 ACE_ERROR((LM_ERROR,
00181 "(%P|%t) ERROR: Dynamic_Cached_Allocator_With_Overflow::free %x"
00182 " more deletes %d than allocs %d from the pool\n",
00183 this,
00184 this->frees_to_pool_.value(),
00185 this->allocs_from_pool_.value()));
00186 }
00187
00188 this->free_list_.add((ACE_Cached_Mem_Pool_Node<char> *) ptr) ;
00189
00190 if (DCPS_debug_level >= 6)
00191 if (this->available() % 500 == 0)
00192 ACE_DEBUG((LM_DEBUG,
00193 "(%P|%t) Dynamic_Cached_Allocator_With_Overflow::malloc %x"
00194 " %d pool allocs %d pool frees with %d available\n",
00195 this, this->allocs_from_pool_.value(), this->frees_to_pool_.value(),
00196 this->available()));
00197 }
00198 }
00199
00200
00201 size_t pool_depth() {
00202 return this->free_list_.size() ;
00203 }
00204
00205
00206
00207
00208
00209 size_t available() {
00210 return free_list_.size();
00211 };
00212
00213
00214 ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> allocs_from_heap_;
00215
00216 ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> allocs_from_pool_;
00217
00218 ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> frees_to_heap_ ;
00219
00220 ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> frees_to_pool_;
00221 private:
00222
00223
00224 unsigned char* begin_;
00225
00226 unsigned char* end_;
00227
00228
00229
00230
00231
00232 ACE_Locked_Free_List<ACE_Cached_Mem_Pool_Node<char>, ACE_LOCK> free_list_;
00233
00234
00235 size_t chunk_size_;
00236 };
00237
00238 }
00239 }
00240
00241 #endif