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 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL
00024
00025 namespace OpenDDS {
00026 namespace DCPS {
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 template <class ACE_LOCK>
00044 class Dynamic_Cached_Allocator_With_Overflow : public ACE_New_Allocator, public PoolAllocationBase {
00045 public:
00046
00047
00048 Dynamic_Cached_Allocator_With_Overflow(size_t n_chunks, size_t chunk_size)
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
00058 end_ = begin_ + n_chunks * chunk_size_;
00059
00060
00061
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 }
00070
00071
00072 ~Dynamic_Cached_Allocator_With_Overflow() {
00073 ACE_Allocator::instance()->free(begin_);
00074 begin_ = 0;
00075 chunk_size_ = 0;
00076 }
00077
00078
00079
00080
00081
00082
00083
00084 void *malloc(size_t nbytes = 0) {
00085
00086 if (nbytes > chunk_size_)
00087 return 0;
00088
00089
00090
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 }
00129
00130
00131
00132
00133
00134
00135
00136 virtual void *calloc(size_t ,
00137 char = '\0') {
00138 ACE_NOTSUP_RETURN(0);
00139 }
00140
00141
00142
00143 virtual void *calloc(size_t ,
00144 size_t ,
00145 char = '\0') {
00146 ACE_NOTSUP_RETURN(0);
00147 }
00148
00149
00150 void free(void * ptr) {
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 }
00201
00202
00203 size_t pool_depth() {
00204 return this->free_list_.size() ;
00205 }
00206
00207
00208
00209
00210
00211 size_t available() {
00212 return free_list_.size();
00213 };
00214
00215
00216 ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> allocs_from_heap_;
00217
00218 ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> allocs_from_pool_;
00219
00220 ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> frees_to_heap_ ;
00221
00222 ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long> frees_to_pool_;
00223 private:
00224
00225
00226 unsigned char* begin_;
00227
00228 unsigned char* end_;
00229
00230
00231
00232
00233
00234 ACE_Locked_Free_List<ACE_Cached_Mem_Pool_Node<char>, ACE_LOCK> free_list_;
00235
00236
00237 size_t chunk_size_;
00238 };
00239
00240 }
00241 }
00242
00243 OPENDDS_END_VERSIONED_NAMESPACE_DECL
00244
00245 #endif