This commit is contained in:
邹晓航
2015-01-06 14:03:41 +08:00
parent 27cfb499a2
commit 81affa4ffd
4 changed files with 139 additions and 110 deletions

119
TinySTL/Alloc.cpp Normal file
View File

@@ -0,0 +1,119 @@
#include "Alloc.h"
namespace TinySTL{
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);
}
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);
}
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;
}
//返回一个大小为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);
}
}
}

View File

@@ -47,116 +47,6 @@ namespace TinySTL{
static void deallocate(void *ptr, size_t bytes); static void deallocate(void *ptr, size_t bytes);
static void *reallocate(void *ptr, size_t old_sz, size_t new_sz); static void *reallocate(void *ptr, size_t old_sz, size_t new_sz);
}; };
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);
}
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);
}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;
}
//返回一个大小为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 #endif

View File

@@ -79,9 +79,12 @@
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Alloc.cpp" />
<ClCompile Include="main.cpp" /> <ClCompile Include="main.cpp" />
<ClCompile Include="Profiler\Profiler.cpp" /> <ClCompile Include="Profiler\Profiler.cpp" />
<ClCompile Include="Test\AlgorithmTest.cpp" /> <ClCompile Include="Test\AlgorithmTest.cpp" />
<ClCompile Include="Test\BitmapTest.cpp" />
<ClCompile Include="Test\CircularBufferTest.cpp" />
<ClCompile Include="Test\PairTest.cpp" /> <ClCompile Include="Test\PairTest.cpp" />
<ClCompile Include="Test\PriorityQueueTest.cpp" /> <ClCompile Include="Test\PriorityQueueTest.cpp" />
<ClCompile Include="Test\QueueTest.cpp" /> <ClCompile Include="Test\QueueTest.cpp" />
@@ -110,6 +113,8 @@
<ClInclude Include="String.h" /> <ClInclude Include="String.h" />
<ClInclude Include="SuffixArray.h" /> <ClInclude Include="SuffixArray.h" />
<ClInclude Include="Test\AlgorithmTest.h" /> <ClInclude Include="Test\AlgorithmTest.h" />
<ClInclude Include="Test\BitmapTest.h" />
<ClInclude Include="Test\CircularBufferTest.h" />
<ClInclude Include="Test\PairTest.h" /> <ClInclude Include="Test\PairTest.h" />
<ClInclude Include="Test\PriorityQueueTest.h" /> <ClInclude Include="Test\PriorityQueueTest.h" />
<ClInclude Include="Test\QueueTest.h" /> <ClInclude Include="Test\QueueTest.h" />

View File

@@ -54,6 +54,15 @@
<ClCompile Include="Test\StackTest.cpp"> <ClCompile Include="Test\StackTest.cpp">
<Filter>Test</Filter> <Filter>Test</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Test\BitmapTest.cpp">
<Filter>Test</Filter>
</ClCompile>
<ClCompile Include="Test\CircularBufferTest.cpp">
<Filter>Test</Filter>
</ClCompile>
<ClCompile Include="Alloc.cpp">
<Filter>头文件</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="TypeTraits.h"> <ClInclude Include="TypeTraits.h">
@@ -149,6 +158,12 @@
<ClInclude Include="Test\StackTest.h"> <ClInclude Include="Test\StackTest.h">
<Filter>Test</Filter> <Filter>Test</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Test\BitmapTest.h">
<Filter>Test</Filter>
</ClInclude>
<ClInclude Include="Test\CircularBufferTest.h">
<Filter>Test</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\README.md" /> <None Include="..\README.md" />