SGI STL中的alloc

1. SGI STL实现版本       

         SGI版本由Silicon Graphics Computer System, Inc公司发展,继承HP版本。所以它的每一个头文件也都有HP的版本声明。此外还加上SGI的公司版权声明。主要设计者仍然是STL之父Alexandar Stepanov,被LinuxC++编译器GCC所采用。SGI STL是开源软件,源码可读性非常高。

2. SGI STL的配置器与众不同,其名称为alloc,而且不用传任何参数,所以使用的时候必须写成:

 vector<int , std::alloc> iv   //in GCC  

   STL 标准规格告诉我们,配置器定义于<memory>之中,SGI <memory>内含以下两个头文件:

#include<stl_alloc.h>

#include<stl_construct.h>

具体分工如下图:

模拟实

现代码:

#pragma once
namespace 51CC
{
	template<class T>
		T* _allocate(ptrdiff_t size, T*)
	{
		//set_new_handler(0);
		T *tmp = (T*)(::operator new(size*sizeof(T)));
		if(tmp == 0)
		{
			cerr<<"Out Of Memory."<<endl;
		}
		return tmp;
	}
	template<class T>
		void _deallocate(T *buffer)
	{
		::operator delete(buffer);
	}
	template<class T1, class T2>
		void _construct(T1 *p, const T2 &value)
	{
		new(p) T1(value);
	}
	template<class T>
		void _destroy(T *ptr)
	{
		ptr->~T();
	}
	
	template<class T>
		class allocator
	{
public:
	typedef T value_type;
	typedef T* pointer;
	typedef const T* const_pointer;
	typedef T& reference;
	typedef const T& const_reference;
	typedef size_t  size_type;
	typedef ptrdiff_t  difference_type;
public:
	pointer allocate(size_type n, const void*hint = 0)
	{
		return _allocate(n, (pointer)0);
	}
	void deallocate(pointer p, size_type n)
	{
		_deallocate(p);
	}
	void construct(pointer p, const T &value)
	{
		_construct(p, value);
	}
	void destroy(pointer p)
	{
		_destroy(p);
	}
	};
};

construct() destroy()的示意图:

3. std::alloc中的一级及二级空间配置器模拟实现代码:

#pragma once

#if 0
#include<new>
#define __THROW_BAD_ALLOC throw bad_alloc
#elif !defined(__THROW_BAD_ALLOC)
//#include<iostream.h>
#define __THROW_BAD_ALLOC cout<<"Out Of Memory."<<endl; exit(1)
#endif

template<int inst>
class __malloc_alloc_template
{
public:
	static void* allocate(size_t n)
	{
		void *result = malloc(n);
		if(result == 0)
			result = b(n); //
		return result;
	}
	static void  deallocate(void *p, size_t)
	{
		free(p);
	}
	static void* reallocate(void *p, size_t old_sz, size_t new_sz)
	{
		void *result = realloc(p, new_sz);
		if(0 == result)
			result = oom_realloc(p, new_sz);
		return result;
	}
private:
	static void * oom_malloc(size_t n);
	static void * oom_realloc(void *p, size_t n);
	static void(*__malloc_alloc_oom_handler)();
};

template<int inst>
void(* __malloc_alloc_template<inst>::__malloc_alloc_oom_handler)() = 0;

template<int inst>
void* __malloc_alloc_template<inst>::oom_malloc(size_t n)
{
	void(*my_malloc_handler)();
	void *result;
	for(;;)
	{
		my_malloc_handler = __malloc_alloc_oom_handler;
		if(0 == my_malloc_handler)
		{
			__THROW_BAD_ALLOC;
		}
		(*my_malloc_handler)();
		result = malloc(n);
		if(result)
			return result;
	}
}

template<int inst>
void* __malloc_alloc_template<inst>::oom_realloc(void *p, size_t n)
{
	void(*my_malloc_handler)();
	void *result;
	for(;;)
	{
		my_malloc_handler = __malloc_alloc_oom_handler;
		if(0 == my_malloc_handler)
		{
			__THROW_BAD_ALLOC;
		}
		(*my_malloc_handler)();
		result = realloc(p, n);
		if(result)
			return result;
	}
}

/////////////////////////////////////////////////////////////////////////

enum {__ALIGN = 8};
enum {__MAX_BYTES = 128};
enum {__NFREELISTS = __MAX_BYTES / __ALIGN};

template<bool threads, int inst>
class __default_alloc_template
{
public:
	static void *allocate(size_t n)
	{
		void *result;
		return result;
	}
	static void deallocate(void *p, size_t n);
	static void* reallocate(void *p, size_t old_sz, size_t new_sz);
private:
	static size_t ROUND_UP(size_t bytes)
	{
		return (bytes+__ALIGN-1) & ~(__ALIGN-1);//
	}
	union obj
	{
		union obj * free_list_link;
		char client_data[1];
	};
private:
	static size_t FREELIST_INDEX(size_t bytes)
	{
		return (bytes + __ALIGN - 1) / __ALIGN-1;
	}
private:
	static obj * free_list[__NFREELISTS];
	static char *start_free;
	static char *end_free;
	static size_t heap_size;
};

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



第一级配置器与第二季配置器的包装接口和运用方式:


参考文献:STL源码剖析(简体)



猜你喜欢

转载自blog.csdn.net/zzb2019/article/details/79175305