home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / mysys / my_alloc.c < prev    next >
C/C++ Source or Header  |  2000-09-12  |  4KB  |  155 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17.  
  18. /* Routines to handle mallocing of results which will be freed the same time */
  19.  
  20. #include <global.h>
  21. #include <my_sys.h>
  22. #include <m_string.h>
  23.  
  24. void init_alloc_root(MEM_ROOT *mem_root, uint block_size, uint pre_alloc_size)
  25. {
  26.   mem_root->free=mem_root->used=0;
  27.   mem_root->min_malloc=16;
  28.   mem_root->block_size=block_size-MALLOC_OVERHEAD-sizeof(USED_MEM)-8;
  29.   mem_root->error_handler=0;
  30. #if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
  31.   if (pre_alloc_size)
  32.   {
  33.     if ((mem_root->free = mem_root->pre_alloc=
  34.      (USED_MEM*) my_malloc(pre_alloc_size+ ALIGN_SIZE(sizeof(USED_MEM)),
  35.                    MYF(0))))
  36.     {
  37.       mem_root->free->size=pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM));
  38.       mem_root->free->left=pre_alloc_size;
  39.       mem_root->free->next=0;
  40.     }
  41.   }
  42. #endif
  43. }
  44.  
  45. gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
  46. {
  47. #if defined(HAVE_purify) && defined(EXTRA_DEBUG)
  48.   reg1 USED_MEM *next;
  49.   Size+=ALIGN_SIZE(sizeof(USED_MEM));
  50.  
  51.   if (!(next = (USED_MEM*) my_malloc(Size,MYF(MY_WME))))
  52.   {
  53.     if (mem_root->error_handler)
  54.       (*mem_root->error_handler)();
  55.     return((gptr) 0);                /* purecov: inspected */
  56.   }
  57.   next->next=mem_root->used;
  58.   mem_root->used=next;
  59.   return (gptr) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM)));
  60. #else
  61.   uint get_size,max_left;
  62.   gptr point;
  63.   reg1 USED_MEM *next;
  64.   reg2 USED_MEM **prev;
  65.  
  66.   Size= ALIGN_SIZE(Size);
  67.   prev= &mem_root->free;
  68.   max_left=0;
  69.   for (next= *prev ; next && next->left < Size ; next= next->next)
  70.   {
  71.     if (next->left > max_left)
  72.       max_left=next->left;
  73.     prev= &next->next;
  74.   }
  75.   if (! next)
  76.   {                        /* Time to alloc new block */
  77.     get_size= Size+ALIGN_SIZE(sizeof(USED_MEM));
  78.     if (max_left*4 < mem_root->block_size && get_size < mem_root->block_size)
  79.       get_size=mem_root->block_size;        /* Normal alloc */
  80.  
  81.     if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME))))
  82.     {
  83.       if (mem_root->error_handler)
  84.     (*mem_root->error_handler)();
  85.       return((gptr) 0);                /* purecov: inspected */
  86.     }
  87.     next->next= *prev;
  88.     next->size= get_size;
  89.     next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM));
  90.     *prev=next;
  91.   }
  92.   point= (gptr) ((char*) next+ (next->size-next->left));
  93.   if ((next->left-= Size) < mem_root->min_malloc)
  94.   {                        /* Full block */
  95.     *prev=next->next;                /* Remove block from list */
  96.     next->next=mem_root->used;
  97.     mem_root->used=next;
  98.   }
  99.   return(point);
  100. #endif
  101. }
  102.  
  103.     /* deallocate everything used by alloc_root */
  104.  
  105. void free_root(MEM_ROOT *root, myf MyFlags)
  106. {
  107.   reg1 USED_MEM *next,*old;
  108.   DBUG_ENTER("free_root");
  109.  
  110.   if (!root)
  111.     DBUG_VOID_RETURN; /* purecov: inspected */
  112.   if (!(MyFlags & MY_KEEP_PREALLOC))
  113.     root->pre_alloc=0;
  114.  
  115.   for ( next=root->used; next ;)
  116.   {
  117.     old=next; next= next->next ;
  118.     if (old != root->pre_alloc)
  119.       my_free((gptr) old,MYF(0));
  120.   }
  121.   for (next= root->free ; next ; )
  122.   {
  123.     old=next; next= next->next ;
  124.     if (old != root->pre_alloc)
  125.       my_free((gptr) old,MYF(0));
  126.   }
  127.   root->used=root->free=0;
  128.   if (root->pre_alloc)
  129.   {
  130.     root->free=root->pre_alloc;
  131.     root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(USED_MEM));
  132.     root->free->next=0;
  133.   }
  134.   DBUG_VOID_RETURN;
  135. }
  136.  
  137.  
  138. char *strdup_root(MEM_ROOT *root,const char *str)
  139. {
  140.   uint len= (uint) strlen(str)+1;
  141.   char *pos;
  142.   if ((pos=alloc_root(root,len)))
  143.     memcpy(pos,str,len);
  144.   return pos;
  145. }
  146.  
  147.  
  148. char *memdup_root(MEM_ROOT *root,const char *str,uint len)
  149. {
  150.   char *pos;
  151.   if ((pos=alloc_root(root,len)))
  152.     memcpy(pos,str,len);
  153.   return pos;
  154. }
  155.