00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00016 #include <ders/mem_pool.hpp>
00017 #include <vector>
00018 #include <stdio.h>
00019 #include <ders/hash_vec.hpp>
00020
00021 namespace {
00022
00023 using namespace std;
00024 using namespace ders;
00025
00026 struct mp_impl {
00027 static const size_t MOS1=256;
00028 static const size_t MOS2=8*1024;
00029 static const size_t SZVP=sizeof(void*);
00030 static const size_t SZVP8=SZVP*8;
00031 static const size_t HEADS1_SIZE=(MOS1-1)/SZVP+1;
00032 static const size_t HEADS2_SIZE=(MOS2-MOS1-1)/SZVP8+1;
00033
00034 size_t max_chunk_size;
00035 size_t min_objs_in_chunk;
00036 vector<void*> chunks;
00037 void* heads1[HEADS1_SIZE];
00038 void* heads2[HEADS2_SIZE];
00039 #ifndef NDEBUG
00040 hash_vec<void*, size_t> allocated;
00041 #endif
00042
00043 mp_impl(size_t mcs, size_t moic);
00044 ~mp_impl();
00045
00046 void* new_chunk(size_t size);
00047 void format_new_chunk(void*& head, size_t size, size_t grid);
00048 };
00049
00050 mp_impl::mp_impl(size_t mcs, size_t moic)
00051 #ifndef NDEBUG
00052 : allocated(1001)
00053 #endif
00054 {
00055 assert(moic>=1);
00056
00057 max_chunk_size=mcs;
00058 min_objs_in_chunk=moic;
00059 chunks.reserve(64);
00060 for (int i=0, end=HEADS1_SIZE; i<end; i++) heads1[i]=0;
00061 for (int i=0, end=HEADS2_SIZE; i<end; i++) heads2[i]=0;
00062 }
00063
00064 mp_impl::~mp_impl()
00065 {
00066 for (int i=0, end=chunks.size(); i<end; i++)
00067 operator delete(chunks[i]);
00068 }
00069
00070 void* mp_impl::new_chunk(size_t size)
00071 {
00072 chunks.reserve(chunks.size()+1);
00073 chunks.push_back(operator new(size));
00074
00075 return chunks.back();
00076 }
00077
00078 void mp_impl::format_new_chunk(void*& head, size_t size, size_t grid)
00079 {
00080 size_t size2=(size+grid-1)/grid*grid;
00081
00082 size_t n=max_chunk_size/size2;
00083 if (n<min_objs_in_chunk) n=min_objs_in_chunk;
00084
00085 typedef unsigned char uchar;
00086 uchar *first=static_cast<uchar*>(new_chunk(size2*n)),
00087 *last=first+size2*(n-1);
00088
00089 for (uchar *ptr=first; ptr!=last; ptr+=size2)
00090 *reinterpret_cast<void**>(ptr)=ptr+size2;
00091
00092 *reinterpret_cast<void**>(last)=head;
00093 head=first;
00094 }
00095
00096 }
00097
00098 #define IMPL static_cast<mp_impl*>(impl)
00099
00100 namespace ders {
00101
00102 mem_pool::mem_pool(size_t max_chunk_size, size_t min_objs_in_chunk) :
00103 impl(new mp_impl(max_chunk_size, min_objs_in_chunk))
00104 {
00105 }
00106
00107 mem_pool::~mem_pool()
00108 {
00109 #ifndef NDEBUG
00110 for (int i=0; i<IMPL->allocated.size(); i++) {
00111 fprintf(stderr, "(%p,%d)", IMPL->allocated.key(i), (int)IMPL->allocated.
00112 val(i));
00113 }
00114
00115 assert(IMPL->allocated.size()==0);
00116 #endif
00117 delete IMPL;
00118 }
00119
00120 void* mem_pool::allocate(size_t size)
00121 {
00122 assert(size>0);
00123 void* ret;
00124
00125 if (size<=mp_impl::MOS1) {
00126 void*& head=IMPL->heads1[(size-1)/mp_impl::SZVP];
00127 if (!head) IMPL->format_new_chunk(head, size, mp_impl::SZVP);
00128
00129 ret=head;
00130 head=*reinterpret_cast<void**>(head);
00131 }
00132 else if (size<=mp_impl::MOS2) {
00133 void*& head=IMPL->heads2[(size-mp_impl::MOS1-1)/mp_impl::SZVP8];
00134 if (!head) IMPL->format_new_chunk(head, size, mp_impl::SZVP8);
00135
00136 ret=head;
00137 head=*reinterpret_cast<void**>(head);
00138 }
00139 else ret=operator new(size);
00140
00141 #ifndef NDEBUG
00142 int pos=IMPL->allocated.insert(ret, size);
00143 assert(pos!=-1);
00144 #endif
00145 return ret;
00146 }
00147
00148 void mem_pool::deallocate(void* ptr, size_t size)
00149 {
00150 #ifndef NDEBUG
00151 int pos=IMPL->allocated.find(ptr);
00152 assert(pos!=-1);
00153 assert(IMPL->allocated.val(pos)==size);
00154 IMPL->allocated.erase(pos);
00155 #endif
00156
00157 if (size<=mp_impl::MOS1) {
00158 void*& head=IMPL->heads1[(size-1)/mp_impl::SZVP];
00159
00160 *reinterpret_cast<void**>(ptr)=head;
00161 head=ptr;
00162 }
00163 else if (size<=mp_impl::MOS2) {
00164 void*& head=IMPL->heads2[(size-mp_impl::MOS1-1)/mp_impl::SZVP8];
00165
00166 *reinterpret_cast<void**>(ptr)=head;
00167 head=ptr;
00168 }
00169 else operator delete(ptr);
00170 }
00171
00172 }
00173