From 90699d642eeffda8316a30500e2b282b2a839d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E6=99=93=E8=88=AA?= <1210603696@qq.com> Date: Wed, 17 Sep 2014 14:52:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=A9=BA=E9=97=B4=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TinySTL/Alloc.h | 107 ++++++++++++++++++++++++++++++++++++++++++++++- TinySTL/main.cpp | 9 +++- 2 files changed, 113 insertions(+), 3 deletions(-) diff --git a/TinySTL/Alloc.h b/TinySTL/Alloc.h index d188df6..aea662d 100644 --- a/TinySTL/Alloc.h +++ b/TinySTL/Alloc.h @@ -1,6 +1,8 @@ #ifndef _ALLOC_H_ #define _ALLOC_H_ +#include + namespace TinySTL{ /* @@ -9,8 +11,9 @@ namespace TinySTL{ class alloc{ private: enum EAlign{ ALIGN = 8};//小型区块的上调边界 - enum EMaxBytes{ MAXBYTES = 128};//小型区块的上限 + enum EMaxBytes{ MAXBYTES = 128};//小型区块的上限,超过的区块由malloc分配 enum ENFreeLists{ NFREELISTS = (EMaxBytes::MAXBYTES / EAlign::ALIGN)};//free-lists的个数 + enum ENObjs{ NOBJS = 20};//每次增加的节点数 private: //free-lists的节点构造 union obj{ @@ -50,6 +53,108 @@ namespace TinySTL{ 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); + } + size_t index = FREELIST_INDEX(bytes); + obj *list = free_list[index]; + if (list){//此list还有空间给我们 + free_list[index] = list->next; + return list; + }else{//此list没有足够的空间,需要从内存池里面取空间 + return refill(ROUND_UP(bytes)); + } + } + void alloc::deallocate(void *ptr, size_t bytes){ + if (bytes > EMaxBytes::MAXBYTES){ + free(ptr); + } + size_t index = FREELIST_INDEX(bytes); + obj *node = static_cast(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; + } + //返回一个大小为n的对象,并且有时候会为适当的free list增加节点 + //假设bytes已经上调为8的倍数 + 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); + //将取出的多余的空间加入到相应的free list里面去 + for (int i = 1;; ++i){ + current_obj = next_obj; + next_obj = (obj *)((char *)next_obj + bytes); + if (nobjs - 1 == i){ + current_obj->next = 0; + break; + }else{ + current_obj->next = next_obj; + } + } + return result; + } + } + //假设bytes已经上调为8的倍数 + 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 += total_bytes; + return result; + }else{//内存池剩余空间连一个区块的大小都无法提供 + size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4); + 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){ + 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){ + *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); + } + } } #endif \ No newline at end of file diff --git a/TinySTL/main.cpp b/TinySTL/main.cpp index 55e903a..875d275 100644 --- a/TinySTL/main.cpp +++ b/TinySTL/main.cpp @@ -1,12 +1,17 @@ #include +#include +#include "Alloc.h" #include "Construct.h" using namespace std; int main(){ - cout << "Holle World" << endl; - + for (int i = 1; i != 100000; ++i){ + TinySTL::alloc::allocate(i % 128 * sizeof(int)); + //std::allocator alloc; alloc.allocate(i % 128); + //malloc(i % 128 * sizeof(int)); + } system("pause"); return 0; } \ No newline at end of file