STL学习之路之配置器(内存池)

#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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值