C++实战项目TinySTL之八:alloc.cpp

最近看了《STL源码剖析》和侯捷老师的STL课程,打算做一个小型的STL,在增加项目经验的同时也顺带复习STL和数据结构相关的知识。整个系列完全参考岚岚路的博客和github上的一个STL项目项目地址

任务

对alloc.h中各个内存分配函数的实现

#include"../Alloc.h"
namespace mySTL {
    
    
	char *alloc::start_free = 0;
	char *alloc::end_free = 0;
	size_t alloc::heap_size = 0;
	//做初始化

	alloc::obj *alloc::free_list[alloc::ENFreeLists::NFREELISTS] = {
    
    
		0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	};
	void *alloc::allocate(size_t bytes) {
    
    
		if (bytes > EMaxBytes::MAXBYTES) {
    
    
			return malloc(bytes);//比128bytes大直接调用malloc
		}
		size_t index = FREELIST_INDEX(bytes);//选择对应的区块 128/n + 1
		obj *list = free_list[index];//选定区块
		if (list) {
    
    
			free_list[index] = list->next;//把后一块内存的地址存入,便于下次取用
			return list;//如果这块内存恰好空着,把这块内存送出
		}
		else {
    
    
			return refill(ROUND_UP(bytes));
		}
	}
	void alloc::deallocate(void *ptr, size_t bytes) {
    
    
		if (bytes > EMaxBytes::MAXBYTES) {
    
    
			free(ptr);//用malloc取来的内存用free还
		}
		else {
    
    
			size_t index = FREELIST_INDEX(bytes);//该还去哪块
			obj *node = static_cast<obj *>(ptr);//强制转型
			node->next = free_list[index];
			free_list[index] = node;//将这块内存放在最前方,之前的内存挂在其后
		}
	}
	void *alloc::reallocate(void *ptr, size_t old_sz,size_t new_sz) {
    
    
		deallocate(ptr, old_sz);//销毁
		ptr = allocate(new_sz);//重分配
		return ptr;
	}
	void *alloc::refill(size_t bytes) {
    
    
		size_t nobjs = ENObjs::NOBJS;
		char *chunk = chunk_alloc(bytes, nobjs);//直接从内存池取
		obj **my_free_list = 0;
		obj *result = 0;
		obj *current_obj = 0, *next_obj = 0;
		if (nobjs == 1) {
    
    //只够一个对象用,无需分割直接返回
			return chunk;
		}
		else {
    
    
			my_free_list = free_list + FREELIST_INDEX(bytes);
			result = (obj *)(chunk);
			*my_free_list = next_obj = (obj *)(chunk + bytes);
			for (int i = 0;; ++i) {
    
    
				current_obj = next_obj;
				next_obj = (obj *)((char *)next_obj + bytes);
				if (nobjs - 1 == i) {
    
    
					current_obj->next = 0;//分得块数足够,内存已经切完,最后一块指向0,退出循环
					break;
				}
				else {
    
    
					current_obj->next = next_obj;
				}
			}
			return result;
		}
	}

	char *alloc::chunk_alloc(size_t bytes, size_t& nobjs) {
    
    
		char *result = 0;
		size_t total_bytes = bytes * nobjs;
		size_t bytes_left = end_free - start_free;

		if (bytes_left >= total_bytes) {
    
    //内存池剩余空间满足要求
			result = start_free;
			start_free = start_free + total_bytes;
			return result;
		}
		else if (bytes_left >= bytes) {
    
    //虽然不够,但还能够提供一块甚至更多
			nobjs = bytes_left / bytes;
			total_bytes = nobjs * bytes;
			result = start_free;
			start_free = start_free + total_bytes;
			return result;
		}
		else {
    
    
			size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4);
			//向系统所要的内存为两倍的此次需求加上16倍堆数
			if(bytes_left>0){
    
    
				obj **my_free_list = free_list + FREELIST_INDEX(bytes_left);
				((obj *)start_free)->next = *my_free_list;
				*my_free_list = (obj *)start_free;
			}
			start_free = (char *)malloc(bytes_to_get);//要一块新的内存,并把内存起点重新定义
			if (!start_free) {
    
    //malloc没有得到内存
				obj **my_free_list = 0, *p = 0;
				for (int i = 0; i <= EMaxBytes::MAXBYTES; i += EAlign::ALIGN) {
    
    
					my_free_list = free_list + FREELIST_INDEX(i);
					p = *my_free_list;
					if (p != 0) {
    
    //找到碎片,返回
						*my_free_list = p->next;
						start_free = (char *)p;
						end_free = start_free + i;
						return chunk_alloc(bytes, nobjs);
					}
				}
				end_free = 0;
			}
			heap_size += bytes_to_get;//扩充内存
			end_free = start_free + bytes_to_get;//重定义末尾内存
			return chunk_alloc(bytes, nobjs);

		}

	}
}

猜你喜欢

转载自blog.csdn.net/weixin_44537258/article/details/115112403
今日推荐