Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00021 #include <config.h>
00022
00023 #include <drizzled/internal/my_sys.h>
00024 #include <drizzled/internal/m_string.h>
00025
00026 #include <algorithm>
00027
00028 using namespace std;
00029
00030 namespace drizzled
00031 {
00032
00033 static const unsigned int MAX_BLOCK_TO_DROP= 4096;
00034 static const unsigned int MAX_BLOCK_USAGE_BEFORE_DROP= 10;
00035
00054 void memory::Root::init_alloc_root(size_t block_size_arg)
00055 {
00056 free= used= pre_alloc= 0;
00057 min_malloc= 32;
00058 block_size= block_size_arg - memory::ROOT_MIN_BLOCK_SIZE;
00059 error_handler= 0;
00060 block_num= 4;
00061 first_block_usage= 0;
00062 }
00063
00064 memory::Root::~Root()
00065 {
00066 }
00067
00068
00084 void memory::Root::reset_root_defaults(size_t block_size_arg, size_t pre_alloc_size)
00085 {
00086 block_size= block_size_arg - memory::ROOT_MIN_BLOCK_SIZE;
00087 if (pre_alloc_size)
00088 {
00089 size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
00090 if (not pre_alloc || pre_alloc->size != size)
00091 {
00092 memory::internal::UsedMemory *mem, **prev= &this->free;
00093
00094
00095
00096
00097 while (*prev)
00098 {
00099 mem= *prev;
00100 if (mem->size == size)
00101 {
00102
00103 pre_alloc= mem;
00104 return;
00105 }
00106 if (mem->left + ALIGN_SIZE(sizeof(memory::internal::UsedMemory)) == mem->size)
00107 {
00108
00109 *prev= mem->next;
00110 std::free(mem);
00111 }
00112 else
00113 prev= &mem->next;
00114 }
00115
00116 if ((mem= static_cast<memory::internal::UsedMemory *>(malloc(size))))
00117 {
00118 mem->size= size;
00119 mem->left= pre_alloc_size;
00120 mem->next= *prev;
00121 *prev= pre_alloc= mem;
00122 }
00123 else
00124 {
00125 pre_alloc= 0;
00126 }
00127 }
00128 }
00129 else
00130 {
00131 pre_alloc= 0;
00132 }
00133 }
00134
00149 void *memory::Root::alloc_root(size_t length)
00150 {
00151 unsigned char* point;
00152 memory::internal::UsedMemory *next= NULL;
00153 memory::internal::UsedMemory **prev;
00154 assert(alloc_root_inited());
00155
00156 length= ALIGN_SIZE(length);
00157 if ((*(prev= &this->free)) != NULL)
00158 {
00159 if ((*prev)->left < length &&
00160 this->first_block_usage++ >= MAX_BLOCK_USAGE_BEFORE_DROP &&
00161 (*prev)->left < MAX_BLOCK_TO_DROP)
00162 {
00163 next= *prev;
00164 *prev= next->next;
00165 next->next= this->used;
00166 this->used= next;
00167 this->first_block_usage= 0;
00168 }
00169 for (next= *prev ; next && next->left < length ; next= next->next)
00170 prev= &next->next;
00171 }
00172 if (! next)
00173 {
00174 size_t get_size, tmp_block_size;
00175
00176 tmp_block_size= this->block_size * (this->block_num >> 2);
00177 get_size= length+ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
00178 get_size= max(get_size, tmp_block_size);
00179
00180 if (!(next = static_cast<memory::internal::UsedMemory *>(malloc(get_size))))
00181 {
00182 if (this->error_handler)
00183 (*this->error_handler)();
00184 return NULL;
00185 }
00186 this->block_num++;
00187 next->next= *prev;
00188 next->size= get_size;
00189 next->left= get_size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
00190 *prev=next;
00191 }
00192
00193 point= (unsigned char*) ((char*) next+ (next->size-next->left));
00195 if ((next->left-= length) < this->min_malloc)
00196 {
00197 *prev= next->next;
00198 next->next= this->used;
00199 this->used= next;
00200 this->first_block_usage= 0;
00201 }
00202
00203 return point;
00204 }
00205
00206
00229 void *memory::Root::multi_alloc_root(int unused, ...)
00230 {
00231 va_list args;
00232 char **ptr, *start, *res;
00233 size_t tot_length, length;
00234
00235 (void)unused;
00236 va_start(args, unused);
00237 tot_length= 0;
00238 while ((ptr= va_arg(args, char **)))
00239 {
00240 length= va_arg(args, uint);
00241 tot_length+= ALIGN_SIZE(length);
00242 }
00243 va_end(args);
00244
00245 if (!(start= (char*) this->alloc_root(tot_length)))
00246 return(0);
00247
00248 va_start(args, unused);
00249 res= start;
00250 while ((ptr= va_arg(args, char **)))
00251 {
00252 *ptr= res;
00253 length= va_arg(args, uint);
00254 res+= ALIGN_SIZE(length);
00255 }
00256 va_end(args);
00257 return((void*) start);
00258 }
00259
00260 static void trash_mem(memory::internal::UsedMemory *)
00261 {
00262 TRASH(((char*)(x) + (x->size - x->left)), x->left);
00263 }
00264
00269 void memory::Root::mark_blocks_free()
00270 {
00271 memory::internal::UsedMemory *next;
00272 memory::internal::UsedMemory **last;
00273
00274
00275 last= &free;
00276 for (next= free; next; next= *(last= &next->next))
00277 {
00278 next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
00279 trash_mem(next);
00280 }
00281
00282
00283 *last= next= used;
00284
00285
00286 for (; next; next= next->next)
00287 {
00288 next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
00289 trash_mem(next);
00290 }
00291
00292
00293 used= 0;
00294 first_block_usage= 0;
00295 }
00296
00313 void memory::Root::free_root(myf MyFlags)
00314 {
00315 memory::internal::UsedMemory *next,*old;
00316
00317 if (MyFlags & memory::MARK_BLOCKS_FREE)
00318 {
00319 this->mark_blocks_free();
00320 return;
00321 }
00322 if (!(MyFlags & memory::KEEP_PREALLOC))
00323 this->pre_alloc=0;
00324
00325 for (next=this->used; next ;)
00326 {
00327 old=next; next= next->next ;
00328 if (old != this->pre_alloc)
00329 std::free(old);
00330 }
00331 for (next=this->free ; next ;)
00332 {
00333 old=next; next= next->next;
00334 if (old != this->pre_alloc)
00335 std::free(old);
00336 }
00337 this->used=this->free=0;
00338 if (this->pre_alloc)
00339 {
00340 this->free=this->pre_alloc;
00341 this->free->left=this->pre_alloc->size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
00342 trash_mem(this->pre_alloc);
00343 this->free->next=0;
00344 }
00345 this->block_num= 4;
00346 this->first_block_usage= 0;
00347 }
00348
00354 char *memory::Root::strdup_root(const char *str)
00355 {
00356 return strmake_root(str, strlen(str));
00357 }
00358
00370 char *memory::Root::strmake_root(const char *str, size_t len)
00371 {
00372 char *pos;
00373 if ((pos= (char *)alloc_root(len+1)))
00374 {
00375 memcpy(pos,str,len);
00376 pos[len]=0;
00377 }
00378 return pos;
00379 }
00380
00390 void *memory::Root::memdup_root(const void *str, size_t len)
00391 {
00392 void *pos;
00393
00394 if ((pos= this->alloc_root(len)))
00395 memcpy(pos,str,len);
00396
00397 return pos;
00398 }
00399
00400 }