//default_alloc.h
#ifndef DEFAULT_MALLOC_H #define DEFAULT_MALLOC_H
#include <stdlib.h> #include "malloc_alloc.h"
class __default_alloc : public __malloc_alloc { public: void* allocate(size_t n); void deallocate(void* p, size_t n); void* reallocate(void*p, size_t old_sz, size_t new_sz); private: enum {__ALIGN = 8};
enum {__MAX_BYTES = 128};
enum {__NFREELISTS = __MAX_BYTES/__ALIGN};
size_t ROUND_UP(size_t bytes) { return ((bytes) + __ALIGN - 1) & ~(__ALIGN - 1); }
union obj { union obj* free_list_link; char client_data[1]; };
obj* volatile free_list[__NFREELISTS];
size_t FREELIST_INDEX(size_t bytes) { return (((bytes) + __ALIGN - 1) / __ALIGN - 1); }
void* refill(size_t n);
char* chunk_alloc(size_t size, int &nobjs);
char* start_free; char* end_free; size_t heap_size; __default_alloc() { start_free = 0; end_free = 0; heap_size = 0; } };
#endif
//default_alloc.cpp #include "default_alloc.h"
void* __default_alloc::allocate(size_t n) { obj* volatile* my_free_list; obj* result;
if(n > (size_t)__MAX_BYTES) { return __malloc_alloc::allocate(n); }
my_free_list = free_list + FREELIST_INDEX(n); result = *my_free_list; if(result == 0) { void* r = refill(ROUND_UP(n)); return r; } *my_free_list = result->free_list_link; return result; }
void __default_alloc::deallocate(void* p, size_t n) { obj* q = (obj*)p; obj* volatile* my_free_list;
if(n > (size_t)__MAX_BYTES) { __malloc_alloc::deallocate(p, n); return; }
my_free_list = free_list + FREELIST_INDEX(n); q->free_list_link = *my_free_list; *my_free_list = q; }
void* __default_alloc::refill(size_t n) { int nobjs = 20; char* chunk = chunk_alloc(n, nobjs); obj* volatile* my_free_list; obj* result; obj* current_obj; obj* next_obj;
my_free_list = free_list + FREELIST_INDEX(n); result = (obj*)chunk; *my_free_list = next_obj = (obj*)(chunk + n); for(int i = 1; ; ++i) { current_obj = next_obj; next_obj = (obj*)((char*)current_obj + n); if(nobjs - 1 == i) { current_obj->free_list_link = 0; break; } else { current_obj->free_list_link = next_obj; } }
return result; }
char* __default_alloc::chunk_alloc(size_t size, int& nobjs) { char* result; size_t total_bytes = size * nobjs; size_t bytes_left = end_free - start_free;
if(bytes_left >= total_bytes) { result = start_free; start_free += total_bytes; } else if(bytes_left >= size) { nobjs = bytes_left/size; total_bytes = size * nobjs; result = start_free; start_free += total_bytes; return result; } else { size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4); if(bytes_left > 0) { obj* volatile* my_free_list = free_list + FREELIST_INDEX(bytes_left); ((obj*)start_free)->free_list_link = *my_free_list; *my_free_list = (obj*)start_free; }
start_free = (char*)malloc(bytes_to_get); heap_size += bytes_to_get; end_free = start_free + bytes_to_get; return chunk_alloc(size, nobjs); } }
//malloc_alloc.h #ifndef MALLOC_ALLOC_H #define MALLOC_ALLOC_H
#include <stdio.h> #include <stdlib.h>
class __malloc_alloc { public: void* allocate(size_t n); void deallocate(void* p, size_t n); void* reallocate(void* p, size_t old_sz, size_t new_sz); };
#endif
//malloc_alloc.cpp #include "malloc_alloc.h"
void* __malloc_alloc::allocate(size_t n) { void* result = malloc(n); return result; }
void __malloc_alloc::deallocate(void* p, size_t n) { free(p); }
void* __malloc_alloc::reallocate(void* p, size_t old_sz, size_t new_sz) { void* result = realloc(p, new_sz); return result; } |