00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006 #include "vnl_alloc.h"
00007
00008 #include <vcl_cstring.h>
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
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
00044
00045
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
00056
00057 }
00058 }
00059 start_free = (char*)vcl_malloc(bytes_to_get);
00060
00061
00062
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
00072
00073
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
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
00132
00133
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