STL源码剖析0-内存管理

基本是书上原有代码

#ifndef _STL_ALLOC_H
#define _STL_ALLOC_H

#ifndef _BAD_ALLOC
#include <iostream>
#define _BAD_ALLOC std::cerr<<"Out of memory"<<std::endl; exit(1)
#endif // !_BAD_ALLOC

enum { __ALIGN = 8 };			//小区块为8的倍数
enum { __MAX_BYTES = 128 };		//区域最大为128
enum { __NFREELISTS = 16 };		//自由链表个数

template<int inst>
class __malloc_alloc_template
{
private:
	static void *oom_malloc(size_t n);
	static void *oom_realloc(void *p, size_t old_sz, size_t new_sz);
	static void(*oom_handler)();
public:
	static void *allocate(size_t n);
	static void *reallocate(void *p, size_t old_sz, size_t new_sz);
	static void dellocate(void *p, size_t n);
	static void set_handler(void(*f)());
};

template<int inst>
void *__malloc_alloc_template<inst>::allocate(size_t n)
{
	void *result = malloc(n);
	if (!result)
		result = oom_malloc(n);
	return result;
}
template<int inst>
void *__malloc_alloc_template<inst>::reallocate(void *p, size_t old_sz, size_t new_sz)
{
	void *result = realloc(p, new_sz);
	if (!result)
		oom_realloc(p, old_sz, new_sz);
	return result;
}
template<int inst>
void __malloc_alloc_template<inst>::dellocate(void *p, size_t n)
{
	free(p);
}
template<int inst>
void(*__malloc_alloc_template<inst>::oom_handler)() = 0;
template<int inst>
void __malloc_alloc_template<inst>::set_handler(void(*f)())
{
	oom_handler = f;
}
template<int inst>
void *__malloc_alloc_template<inst>::oom_malloc(size_t n)
{
	void *result;
	while (1)
	{
		if (0 == oom_handler) { _BAD_ALLOC; }
		(*oom_handler)();
		if (result = malloc(n))
			return result;
	}
}
template<int inst>
void *__malloc_alloc_template<inst>::oom_realloc(void *p, size_t pld_sz, size_t new_sz)
{
	void *result;
	while (1)
	{
		if (0 == oom_handler) { _BAD_ALLOC; }
		(*oom_handler)();
		if (result = realloc(p, new_sz))
			return result;
	}
}
/*********************************************************************/
typedef __malloc_alloc_template<0> malloc_alloc;
/*********************************************************************/
template <int inst>
class __default_alloc_template
{
private:
	union obj
	{
		union obj * free_list_link;
		char        client_data[1];
	};
private:
	static char *start_free;        //内存池起始位置
	static char *end_free;          //内存池结束位置
	static size_t heap_size;        //内存池大小

									//自由链表数
	static obj *volatile free_list[__NFREELISTS];
	//返回一个大小为n的区块 并且可能向freelist添加几个大小n的区域
	static void *refill(size_t n);
	//配置一块区域 可以容纳nobjs个大小为n的区域 无法容纳 nodjs可能变低
	static char *chunk_alloc(size_t size, int &nobjs);
private:
	static size_t ROUND_UP(size_t bytes)
	{
		return ((bytes + __ALIGN - 1) & ~(__ALIGN - 1));
	}
	//根据bytes决定链表序号
	static size_t FREELIST_INDEX(size_t bytes)
	{
		return ((bytes + __ALIGN - 1) / __ALIGN - 1);
	}
public:
	static void *allocate(size_t n);
	static void dellocate(void *p, size_t n);
	static void *reallocate(void *p, size_t old_sz, size_t new_sz);
};

template <int inst>
typename __default_alloc_template<inst>::obj
*volatile __default_alloc_template<inst>::free_list[__NFREELISTS] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
template <int inst>
char *__default_alloc_template<inst>::start_free = 0;
template <int inst>
char *__default_alloc_template<inst>::end_free = 0;
template <int inst>
size_t __default_alloc_template<inst>::heap_size = 0;

template <int inst>
void *__default_alloc_template<inst>::allocate(size_t n)
{
	obj *volatile*	my_free_list;
	obj				*result;
	if (n > (size_t)__MAX_BYTES)
		return malloc_alloc::allocate(n);
	my_free_list = free_list + FREELIST_INDEX(n);
	result = *my_free_list;
	if (!result)
		return refill(ROUND_UP(n));
	*my_free_list = result->free_list_link;
	return result;
}
template <int inst>
void __default_alloc_template<inst>::dellocate(void *p, size_t n)
{
	obj *volatile *my_free_list;

	if (n > __MAX_BYTES)
		malloc_alloc::dellocate(p, n);
	else
	{
		my_free_list = free_list + FREELIST_INDEX(n);
		((obj*)p)->free_list_link = *my_free_list;
		*my_free_list = (obj*)p;
	}
}
template <int inst>
void *__default_alloc_template<inst>::reallocate(void *p, size_t old_sz, size_t new_sz)
{
	size_t	copy_sz;
	void	*result;
	if (old_sz > (size_t)__MAX_BYTES && new_sz > (size_t)__MAX_BYTES)
		return realloc(p, new_sz);
	if (ROUND_UP(old_sz) == ROUND_UP(new_sz))
		return p;
	result = allocate(new_sz);
	copy_sz = old_sz < new_sz ? old_sz : new_sz;
	memcpy(result, p, copy_sz);
	dellocate(p, old_sz);
	return result;
}
template <int inst>
void *__default_alloc_template<inst>::refill(size_t n)
{
	obj *volatile *my_free_list;
	int nobjs = 20;
	my_free_list = free_list + FREELIST_INDEX(n);
	char *buffer = chunk_alloc(n, nobjs);
	for (int i = 1; i < nobjs; ++i)
	{
		((obj*)(buffer + n*i))->free_list_link = *my_free_list;
		*my_free_list = (obj*)(buffer + n*i);
	}
	return buffer;
}
template <int inst>
char *__default_alloc_template<inst>::chunk_alloc(size_t size, int &nobjs)
{
	size_t total_bytes = size * nobjs;
	size_t bytes_left = end_free - start_free;
	char *result;

	if (bytes_left >= total_bytes)
	{
		result = start_free;
		start_free += total_bytes;
		return result;
	}
	else if (bytes_left >= size)
	{
		nobjs = bytes_left / size;
		result = start_free;
		start_free += (nobjs * size);
		return result;
	}
	else
	{
		size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4);

		if (bytes_left > 0)
		{
			obj *volatile *my_free_list = free_list + FREELIST_INDEX(bytes_left);
			((obj*)start_free)->free_list_link = *my_free_list;
			*my_free_list = (obj*)start_free;
		}
		start_free = (char*)malloc(bytes_to_get);
		if (0 == start_free)
		{
			int i;
			obj *volatile *my_free_list, *p;
			for (i = size; i <= __MAX_BYTES; i += __ALIGN)
			{
				my_free_list = free_list + FREELIST_INDEX((size_t)i);
				p = *my_free_list;
				if (p)
				{
					*my_free_list = p->free_list_link;
					start_free = (char*)p;
					end_free += i;
					return chunk_alloc(size, nobjs);
				}
			}
			end_free = 0;
			start_free = (char*)malloc_alloc::allocate(bytes_to_get);
		}
		end_free = start_free + bytes_to_get;
		heap_size = bytes_left;
		return chunk_alloc(size, nobjs);
	}
}
/***********************************************************************/
typedef __default_alloc_template<0> alloc;
/***********************************************************************/

#endif // !_STL_ALLOC_H


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值