#include <iostream>
#include <cstddef>
// 内存块结构体
union obj {
union obj* free_list_link; // 指向下一个空闲内存块的指针
char client_data[1]; // 实际存储数据的位置
};
// 二级空间配置器类
class DefaultAllocTemplate {
private:
// 自由链表数组,每个元素指向一个空闲内存块链表
static obj* volatile free_list[16];
// 计算需要的内存块大小对应的自由链表索引
static size_t FREELIST_INDEX(size_t bytes) {
return ((bytes + 8 - 1) / 8 - 1);
}
// 调整请求的内存大小,使其为 8 的倍数
static size_t ROUND_UP(size_t bytes) {
return (((bytes)+8 - 1) & ~(8 - 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) {
obj* volatile* my_free_list;
obj* result;
// 如果请求的内存大小超过 128 字节,使用一级空间配置器
if (n > 128) {
return std::malloc(n);
}
// 找到对应的自由链表
my_free_list = free_list + FREELIST_INDEX(n);
result = *my_free_list;
// 如果自由链表为空,需要重新填充
if (result == nullptr) {
void* r = refill(ROUND_UP(n));
return r;
}
// 从自由链表中取出一个内存块
*my_free_list = result->free_list_link;
return result;
}
// 释放内存
static void deallocate(void* p, size_t n) {
obj* q = static_cast<obj*>(p);
obj* volatile* my_free_list;
// 如果释放的内存大小超过 128 字节,使用一级空间配置器的释放方法
if (n > 128) {
std::free(p);
return;
}
// 找到对应的自由链表
my_free_list = free_list + FREELIST_INDEX(n);
// 将释放的内存块插入自由链表头部
q->free_list_link = *my_free_list;
*my_free_list = q;
}
};
// 初始化静态成员变量
obj* volatile DefaultAllocTemplate::free_list[16] = { nullptr };
char* DefaultAllocTemplate::start_free = nullptr;
char* DefaultAllocTemplate::end_free = nullptr;
size_t DefaultAllocTemplate::heap_size = 0;
// 从内存池中取出内存块填充自由链表
void* DefaultAllocTemplate::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;
// 如果只分配到一个内存块,直接返回给调用者
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 (int i = 1; ; i++) {
current_obj = next_obj;
next_obj = (obj*)((char*)next_obj + n);
if (i == nobjs - 1) {
current_obj->free_list_link = nullptr;
break;
}
else {
current_obj->free_list_link = next_obj;
}
}
return result;
}
// 从操作系统申请一大块内存作为内存池
char* DefaultAllocTemplate::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*)std::malloc(bytes_to_get);
if (start_free == nullptr) {
// 如果申请失败,尝试从其他自由链表中获取内存
obj* volatile* my_free_list;
obj* p;
for (size_t i = size; i <= 128; i += 8) {
my_free_list = free_list + FREELIST_INDEX(i);
p = *my_free_list;
if (p != nullptr) {
*my_free_list = p->free_list_link;
start_free = (char*)p;
end_free = start_free + i;
return chunk_alloc(size, nobjs);
}
}
// 如果还是失败,调用一级空间配置器的异常处理机制
std::abort();
}
heap_size += bytes_to_get;
end_free = start_free + bytes_to_get;
return chunk_alloc(size, nobjs);
}
}
// 测试代码
int main() {
// 分配一个 20 字节的内存块
void* p = DefaultAllocTemplate::allocate(20);
// 释放该内存块
DefaultAllocTemplate::deallocate(p, 20);
return 0;
}