最近开始看侯捷先生的《STL源码剖析》,自己下载了SGI STL源码,然后自己敲了代码,在这里写下笔记,记录下自己学习过程。
下面是没有加上多线程安全的default_alloc_template模板类以及实现代码:(⊙o⊙)… 本人比较懒,自己写的注释都写在书上了,觉得自己敲出来理解的更加透彻些。
template <bool threads , int inst>
class __default_alloc_template{
private:
enum {_ALIGN = 8};
enum {_MAX_BYTES = 128};
enum {_NFREELISTS = 16};
union Obj {
union Obj *free_list_link;
char client_data[1];
};
static Obj* volatile free_list[_NFREELISTS];
static size_t FREELIST_INDEX(size_t bytes) {
return ( (bytes + _ALIGN - 1) / _ALIGN - 1) ;
}
static size_t ROUND_UP(size_t n){
return ((n + _ALIGN - 1) & ~(_ALIGN - 1));
}
static void *refill(size_t n);
static char *chunk_alloc(size_t size , int &nobjs);
static char *start_free;
static char *end_free;
static size_t heap_size;
public:
static void *allocate(size_t n);
static void deallocate(void *p , size_t n);
static void *reallocate(void *p , size_t old_sz , size_t new_sz);
};
template <bool threads , int inst>
char * __default_alloc_template<threads , inst> ::start_free = 0;
template <bool threads , int inst>
char * __default_alloc_template<threads , inst> ::end_free = 0;
template <bool threads , int inst>
char * __default_alloc_template<threads , inst> ::heap_size = 0;
template <bool threads , int inst>
char * __default_alloc_template<threads , inst> :: free_list[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
template <bool threads , int inst>
static void * __default_alloc_template<threads , inst> :: allocate(size_t n)
{
if (n > _MAX_BYTES){
return malloc_alloc::allocate(n);
}
Obj *volatile *my_free_list;
Obj * result;
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;
}
template <bool threads , int inst>
void __default_alloc_template<threads , inst> :: deallocate(void *p , size_t n)
{
if ( n > _MAX_BYTES) {
malloc_alloc::deallocate(p , n)
return ;
}
Obj *q = (Obj *)p;
Obj *volatile *my_free_list = free_list + FREELIST_INDEX(n);
q->free_list_link = *my_free_list;
*my_free_list->free_list_link = q;
}
template <bool threads , int inst>
void *__default_alloc_template<threads , inst>::refill(size_t n)
{
int nobjs = 20;
char *chunk = chunk_alloc(n , nobjs)
Obj * volatile *my_free_list;
Obj * result;
Obj * current_obj , *next_obj;
int i;
if( nobjs == 1)
return chunk;
my_free_list = free_list + FREELIST_INDEX(n);
result = (Obj *)chunk;
*my_free_list = next_obj = (Obj *)(chunk + n);
for (i = 1 ; ; ++i ) {
current_obj = next_obj;
if (nobjs - 1 == i){
current_obj -> free_list_link = 0;
break;
}
else {
current_obj->free_list_link = next_obj;
}
}
}
template <bool threads , int inst>
char *__default_alloc_template<threads , inst>::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;
return result;
}
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);
if (start_free == 0){
int i;
Obj *volatile *my_free_list , *p;
for( i = size ; i <= _MAX_BYTES ; i += _ALIGN){
my_free_list = free_list + FREELIST_INDEX(i);
p = *my_free_list;
if (p != 0){
*my_free_list = p->free_list_link;
start_free = (char *)p;
end_free = start_free + i;
return chunk_alloc(size , nobjs);
}
}
end_free = 0;
start_free = (char *) malloc_alloc::allocate(bytes_to_get);
}
heap_size += bytes_to_get;
end_free = start_free + bytes_to_get;
return chunk_alloc(size , nobjs);
}
}