#ifndef TESTALLOC_H
#define TESTALLOC_H
namespace Test{
template<int _inst>
class __malloc_alloc_template{
private:
static void* _S_oom_malloc(size_t n);
static void* _S_oom_realloc(void* p, size_t n);
static void (*__malloc_alloc_oom_handler)();
public:
static void* allocate(size_t n){
void* _p = malloc(n);
if(!_p)
_p = _S_oom_malloc(n);
return _p;
}
static void* reallocate(void* p, size_t n){
void* _p = realloc(p, n);
if (!_p)
_p = _S_oom_realloc(p, n);
return _p;
}
static void deallocate(void* p, size_t n){
free(p);
}
//定义一个返回类型为函数指针类型的一个函数
//返回的函数类型为 void (*)();
//参数类型为void (*)(),也就是void (*pfn)()
static void (*__set_malloc_handler(void (*pfn)()))(){
void (*_old)() = __malloc_alloc_oom_handler;
__malloc_alloc_oom_handler = pfn;
return _old;
}
};
template<int _inst>
void (*Test::__malloc_alloc_template<_inst>::__malloc_alloc_oom_handler)() = 0;
template<int _inst>
void* Test::__malloc_alloc_template<_inst>::_S_oom_realloc( void* p, size_t n )
{
void (*_old)();
void* result = NULL;
for(;;){
_old = __malloc_alloc_oom_handler;
if (__malloc_alloc_oom_handler == 0)
{
//
}
result = realloc(p, n);
if (result) return result;
}
}
template<int _inst>
void* Test::__malloc_alloc_template<_inst>::_S_oom_malloc( size_t n )
{
void (*_old)();
void* result = NULL;
for (;;)
{
_old = __malloc_alloc_oom_handler;
if (__malloc_alloc_oom_handler == NULL)
{
//
}
result = malloc(n);
if (result) return result;
}
}
typedef __malloc_alloc_template<0> malloc_alloc;
template<class _Tp, class _Alloc>
class simple_alloc{
public:
static _Tp* allocate(size_t n){
return n > 0 ? (_Tp*)_Alloc::allocate(n * sizeof(_Tp)) : 0;
}
static _Tp* allocate(){
return (_Tp*)Alloc::allocate(sizeof(_Tp));
}
static void deallocate(_Tp* p, size_t n){
if (p) _Alloc::deallocate(p, n * sizeof(_Tp));
}
static void deallocate(_Tp* p){
_Alloc::deallocate(p, sizeof(_Tp));
}
};
template<bool threads, int inst>
class __default_alloc_template{
private:
enum {ALIGN = 8};
enum {MAX_BYTES = 128};
enum{NFREELISTS = 16};
union _Obj{
union _Obj* _freelist; //指向下一个
char _clientdata[1]; //为了减少内存浪费
};
static _Obj* volatile _S_freelist[NFREELISTS];
static size_t _S_round_up(size_t n){
return (n + size_t(ALIGN) - 1) & ~(size_t(ALIGN) - 1); //8的整数倍,末3位一定是000,并且是比n大小于7的数
}
static size_t _S_freelist_index(size_t n){
return (n + (size_t)ALIGN - 1) / (size_t)ALIGN - 1;
}
static char* _start;
static char* _end;
static size_t _heapsize;
static void* _S_refill(size_t n);
static char* _S_chunk_alloc(size_t n, int& nobjs);
public:
static void* allocate(size_t n){
void* ret = NULL;
if (n > MAX_BYTES)
{
ret = malloc_alloc::allocate(n);
}
else{
_Obj* volatile * freelist = _S_freelist + _S_freelist_index(n); //所处的区块
_Obj* result = *freelist;
if (result == NULL){
ret = _S_refill(_S_round_up(n)); //不足,填充
}
else{
*freelist = result->_freelist; //指向下一个
ret = result; //把当前的拿出去使用
}
}
return ret;
}
static void deallocate(void* p, size_t n){
if (n > MAX_BYTES){
malloc_alloc::deallocate(p, n);
}else{
_Obj* volatile* freelist = _S_freelist + _S_freelist_index(n);
_Obj* result = (_Obj*)p;
result->_freelist = *freelist; //指向当前的
*freelist = result; //加入到当前列表中
}
}
static void* reallocate(void* p, size_t old_sz, size_t new_sz);
};
typedef __default_alloc_template<true, 0> alloc;
typedef __default_alloc_template<false, 0> single_client_alloc;
template<bool threads, int inst>
char* Test::__default_alloc_template<threads, inst>::_start = NULL;
template<bool threads, int inst>
char* Test::__default_alloc_template<threads, inst>::_end = NULL;
template<bool threads, int inst>
size_t Test::__default_alloc_template<threads, inst>::_heapsize = 0;
template<bool threads, int inst>
typename Test::__default_alloc_template<threads, inst>::_Obj* volatile
Test::__default_alloc_template<threads, inst>::_S_freelist[
Test::__default_alloc_template<threads, inst>::NFREELISTS] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
template<bool threads, int inst>
void* Test::__default_alloc_template<threads, inst>::reallocate( void* p, size_t old_sz, size_t new_sz )
{
if (old_sz > (size_t)MAX_BYTES && new_sz > (size_t)MAX_BYTES)
{
return realloc(p, new_sz);
}
if (_S_round_up(new_sz) == _S_round_up(old_sz)) return p;
void* result = allocate(new_sz);
size_t copy_sz = new_sz > old_sz ? old_sz : new_sz;
memcpy(result, p, copy_sz);
deallocate(p, old_sz);
return result;
}
template<bool threads, int inst>
char* Test::__default_alloc_template<threads, inst>::_S_chunk_alloc( size_t n, int& nobjs )
{
char* result = NULL;
size_t totalbytes = nobjs * n;
size_t leftbytes = _end - _start;
if (leftbytes >= totalbytes){ //空间充足
result = _start;
_start += totalbytes;
return result;
}else if (leftbytes >= n) //至少还能满足一个
{
nobjs = int(leftbytes / n);
totalbytes = nobjs * n;
result = _start;
_start += totalbytes;
return result;
}else{
size_t realbytes = 2 * totalbytes + _S_round_up(_heapsize >> 4);
if (leftbytes > 0){
_Obj* volatile* freelist = _S_freelist + _S_freelist_index(leftbytes);//剩余的对应的区块位置
((_Obj*)_start)->_freelist = *freelist;
*freelist = (_Obj*)_start;
}
_start = (char*)malloc(realbytes);
if (_start == NULL){ //分配失败了,没有多余的空间,去看看以前还有什么剩余的
_Obj* volatile* freelist = NULL;
_Obj* p = NULL;
for (size_t i = n; i <= (size_t)MAX_BYTES; i +=(size_t)ALIGN)
{
freelist = _S_freelist + _S_freelist_index(i);
p = *freelist;
if (p != 0){
*freelist = p->_freelist;
_start = (char*)p;
_end = _start + i;
return _S_chunk_alloc(n, nobjs);
}
}
_end = NULL;
_start = (char*)malloc_alloc::allocate(realbytes);
}
_heapsize += realbytes;
_end = _start + _heapsize;
return _S_chunk_alloc(n, nobjs);
}
}
template<bool threads, int inst>
void* Test::__default_alloc_template<threads, inst>::_S_refill( size_t n )
{
int nobjs = 20;
char* chunk = _S_chunk_alloc(n, nobjs);
//只分配了一个
if (nobjs == 1)
return chunk;
_Obj* volatile* freelist = _S_freelist + _S_freelist_index(n);
_Obj* result = (_Obj*)chunk; //拿出去第一个,剩下的存了
_Obj* current = result;
_Obj* next = (_Obj*)(chunk + n);
*freelist = next;
for (int i = 1; ; i++) //把分配得到的内存加入列表中
{
current = next;
next = (_Obj*)((char*)next + n); //按字节偏移
if (i == nobjs - 1)
{
current->_freelist = NULL;
break;
}else{
current->_freelist = next;
}
}
return result;
}
}
#endif
STL学习之路之配置器(内存池)
最新推荐文章于 2021-06-29 11:16:06 发布