#pragma once
#include//為了malloc、free
#include#define __throw_bad_alloc std::cerr<
class onespce
// 對free的封裝
static void deallocate(void *p, size_t /* n */) //這個size_t完全可以不要,但是為了統一介面,加上了這個size_t
// 對realloc的封裝---該函式基本不用
static void * reallocate(void *p, size_t /* old_sz */, size_t new_sz)
// 模擬set_new_handle
// 該函式的引數為函式指標,返回值型別也為函式指標
// void (* set_malloc_handler( void (*f)() ) )()
typedef void(*pfunc)();
static pfunc set_malloc_handler(pfunc f)
//static void(*set_malloc_handler(void(*f)()))() };
void(*onespce::__malloc_alloc_oom_handler)() = 0; //如果沒有設定的話,在下面的函式就只能會拋異常
// malloc申請空間失敗時代用該函式
void * onespce::oom_malloc(size_t n)
// 如果設定,執行使用者提供的空間不足應對措施
(*my_malloc_handler)();
// 繼續申請空間,可能就會申請成功
result = malloc(n);
if (result)
return(result); }}
// 類似oom_malloc
void* onespce::oom_realloc(void *p,size_t n)
(*my_malloc_handler)(); //呼叫處理例程,企圖釋放記憶體
result = realloc(p, n); //再次嘗試設定記憶體
if (result)
return(result);
}}
class __default_alloc_template
; // 如果使用者所需記憶體不是8的整數倍,向上對齊到8的整數倍
enum ; // 大小記憶體塊的分界線
enum ; // 採用雜湊桶儲存小塊記憶體時所需桶的個數
// 如果使用者所需記憶體塊不是8的整數倍,向上對齊到8的整數倍
static size_t round_up(size_t bytes)
private:
// 用聯合體來維護鍊錶結構----下面解釋
union obj
;private:
static obj * free_list[__nfreelists];
// 雜湊函式,根據使用者提供位元組數找到對應的桶號
static size_t freelist_index(size_t bytes)
// start_free與end_free用來標記記憶體池中大塊記憶體的起始與末尾位置
static char *start_free;
static char *end_free;
// 用來記錄該空間配置器已經想系統索要了多少的記憶體塊
static size_t heap_size;
// ...
} ;char* twospace::start_free = 0;
char* twospace::end_free = 0;
size_t twospace::heap_size = 0;
twospace::obj* twospace::free_list[__nfreelists] = ;
union obj
;
空間配置函式和空間釋放函式static void * allocate(size_t n)
// 根據使用者所需位元組找到對應的桶號
my_free_list = free_list + freelist_index(n);
result = *my_free_list;
// 如果該桶中沒有記憶體塊時,向該桶中補充空間
if (result == 0)
// 維護桶中剩餘記憶體塊的鏈式關係
// 函式功能:使用者將空間歸還給空間配置器
static void deallocate(void *p, size_t n)
// 找到對應的雜湊桶,將記憶體掛在雜湊桶中
重新填充 free list
// 函式功能:向雜湊桶中補充空間
// 引數n:小塊記憶體位元組數
static void* refill(size_t n)
else
}return(result);
}
記憶體池static char* chunk_alloc(size_t size, int& nobjs)
else if (bytes_left >= size)
else
// 通過系統堆向記憶體池補充空間,如果補充成功,遞迴繼續分配
start_free = (char *)malloc(bytes_to_get);
if (0 == start_free)
}// 山窮水盡,只能向一級空間配置器求助
// 注意:此處一定要將end_free置空,因為一級空間配置器一旦拋異常就會出問題
end_free = 0;
start_free = (char*)onespce::allocate(bytes_to_get);
}// 通過系統堆向記憶體池補充空間成功,更新資訊並繼續分配
heap_size += bytes_to_get;
end_free = start_free + bytes_to_get;
return(chunk_alloc(size, nobjs));
} }
// 向系統堆求助,往記憶體池中補充空間
// 計算向記憶體中補充空間大小:本次空間總大小兩倍 + 向系統申請總大小/16
size_t bytes_to_get = 2 * total_bytes + round_up(heap_size >> 4);
空間配置器的預設選擇#ifdef __use_malloc
typedef __malloc_alloc_template<0> malloc_alloc;
typedef malloc_alloc alloc; //令alloc 為一級配置器
#else
typedef __default_alloc_template<__node_allocator_threads> alloc;
#endif // !__use_malloc
STL之空間配置器
空間配置器allocator負責空間的配置和管理,是一種實現了動態空間配置 空間管理 空間釋放的class template。1.空間配置器的標準介面 allocator value type allocator pointer allocator const pointer allocator r...
STL之空間配置器
最近在看侯捷老師寫的stl原始碼剖析,想通過看優秀的 來提高自己的程式設計水平。首先stl提供了六大元件,彼此可以套用使用。借助一張從書上截的圖來表明 container通過allocator來獲取資料儲存空間 algorithms通過迭代器來獲取container的內容,functors可以協助a...
STL 空間配置器
stl有6大元件 容器 演算法 迭代器 仿函式 配接器 分配器。它們之間的密切關係是stl的精髓所在,容器用來存放資料,而容器存在的前提是要有分配器給它分配記憶體,接下來需要實現演算法,迭代器便作為演算法來對容器資料操作的橋梁,演算法可以使用仿函式完成不同的策略變化,配接器可修飾或套接仿函式。說了麼...