core/vnl/vnl_alloc.cxx

Go to the documentation of this file.
00001 // This is core/vnl/vnl_alloc.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 
00006 #include "vnl_alloc.h"
00007 
00008 #include <vcl_cstring.h>  // memcpy() lives here.
00009 #include <vcl_cstdlib.h>
00010 
00011 char*
00012 vnl_alloc::chunk_alloc(vcl_size_t size, int& nobjs)
00013 {
00014   char * result;
00015   vcl_size_t total_bytes = size * nobjs;
00016   vcl_size_t bytes_left = end_free - start_free;
00017 
00018   if (bytes_left >= total_bytes) {
00019     result = start_free;
00020     start_free += total_bytes;
00021     return result;
00022   } else if (bytes_left >= size) {
00023     nobjs = bytes_left/size;
00024     total_bytes = size * nobjs;
00025     result = start_free;
00026     start_free += total_bytes;
00027     return result;
00028   }
00029   else
00030   {
00031     vcl_size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4);
00032     // Try to make use of the left-over piece.
00033     if (bytes_left > 0) {
00034       obj *  * my_free_list =
00035         free_list + FREELIST_INDEX(bytes_left);
00036       ((obj *)start_free) -> free_list_link = *my_free_list;
00037       *my_free_list = (obj *)start_free;
00038     }
00039     start_free = (char*)vcl_malloc(bytes_to_get);
00040     if (0 == start_free)
00041     {
00042       obj *  * my_free_list, *p;
00043       // Try to make do with what we have.  That can't
00044       // hurt.  We do not try smaller requests, since that tends
00045       // to result in disaster on multi-process machines.
00046       for (unsigned int i = size; i <= VNL_ALLOC_MAX_BYTES; i += VNL_ALLOC_ALIGN)
00047       {
00048         my_free_list = free_list + FREELIST_INDEX(i);
00049         p = *my_free_list;
00050         if (0 != p) {
00051           *my_free_list = p -> free_list_link;
00052           start_free = (char *)p;
00053           end_free = start_free + i;
00054           return chunk_alloc(size, nobjs);
00055           // Any leftover piece will eventually make it to the
00056           // right free vcl_list.
00057         }
00058       }
00059       start_free = (char*)vcl_malloc(bytes_to_get);
00060       // This should either throw an
00061       // exception or remedy the situation.  Thus we assume it
00062       // succeeded.
00063     }
00064     heap_size += bytes_to_get;
00065     end_free = start_free + bytes_to_get;
00066     return chunk_alloc(size, nobjs);
00067   }
00068 }
00069 
00070 
00071 /* Returns an object of size n, and optionally adds to size n free vcl_list.*/
00072 /* We assume that n is properly aligned.                                */
00073 /* We hold the allocation lock.                                         */
00074 void* vnl_alloc::refill(vcl_size_t n)
00075 {
00076   int nobjs = 20;
00077   char * chunk = chunk_alloc(n, nobjs);
00078   obj *  * my_free_list;
00079   obj * result;
00080   obj * current_obj, * next_obj;
00081   int i;
00082 
00083   if (1 == nobjs) return chunk;
00084   my_free_list = free_list + FREELIST_INDEX(n);
00085 
00086   /* Build free vcl_list in chunk */
00087   result = (obj *)chunk;
00088   *my_free_list = next_obj = (obj *)(chunk + n);
00089   for (i = 1; ; i++) {
00090     current_obj = next_obj;
00091     next_obj = (obj *)((char *)next_obj + n);
00092     if (nobjs - 1 == i) {
00093       current_obj -> free_list_link = 0;
00094       break;
00095     } else {
00096       current_obj -> free_list_link = next_obj;
00097     }
00098   }
00099   return result;
00100 }
00101 
00102 void*
00103 vnl_alloc::reallocate(void *p,
00104                       vcl_size_t old_sz,
00105                       vcl_size_t new_sz)
00106 {
00107   void * result;
00108   vcl_size_t copy_sz;
00109 
00110   if (old_sz > VNL_ALLOC_MAX_BYTES && new_sz > VNL_ALLOC_MAX_BYTES) {
00111     return vcl_realloc(p, new_sz);
00112   }
00113   if (ROUND_UP(old_sz) == ROUND_UP(new_sz)) return p;
00114   result = allocate(new_sz);
00115   copy_sz = new_sz > old_sz? old_sz : new_sz;
00116   vcl_memcpy(result, p, copy_sz);
00117   deallocate(p, old_sz);
00118   return result;
00119 }
00120 
00121 char *vnl_alloc::start_free = 0;
00122 char *vnl_alloc::end_free = 0;
00123 vcl_size_t vnl_alloc::heap_size = 0;
00124 
00125 vnl_alloc::obj *
00126 vnl_alloc::free_list[VNL_ALLOC_NFREELISTS] =
00127 {
00128   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00129   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00130 };
00131 // The 32 zeros are necessary to make version 4.1 of the SunPro
00132 // compiler happy.  Otherwise it appears to allocate too little
00133 // space for the array.
00134 
00135 #ifdef TEST
00136 #include <vcl_iostream.h>
00137 int main()
00138 {
00139   char* p = (char*)vnl_alloc::allocate(10);
00140   vcl_strcpy(p, "fred\n");
00141   vcl_cerr << p << '\n';
00142   vnl_alloc::deallocate(p,10);
00143 }
00144 
00145 #endif // TEST

Generated on Fri Nov 21 05:06:12 2008 for core/vnl by  doxygen 1.5.1