'allocator'에 해당되는 글 1건

  1. 2009.06.02 stack memory allocator
2009. 6. 2. 12:01

stack memory allocator

// 이 코드는 구현의 예만을 보여주기 위한 것으로
// 실제 사용하기 위해서는 예외 처리나, 메모리 할당 등의 
// 추가적인 구현이 필요.
#include 
#include 

#define SAFE_FREE(buf) if( buf ){ free(buf); buf = 0; }
#define MEM_PTR		unsigned char*

class stack_allocator
{	
	void	_alloc_buffer(size_t stacksize)
	{
		_free_buffer();
		buffer_ = (MEM_PTR)malloc(stacksize);
		top_ = buffer_;
		bottom_ = top_+stacksize;
	}

	void	_free_buffer()
	{
		SAFE_FREE(buffer_);
	}
public:
	stack_allocator(size_t stacksize = 1024):buffer_(0), top_(0), bottom_(0)
	{
		_alloc_buffer(stacksize);
	}

	void*	alloc(size_t size)
	{
		MEM_PTR ret_ptr = top_;
		top_ = ret_ptr + size;
		if( top_ > bottom_ )
		{	// check overflow
			return 0;	//throw exception;
		}
		return ret_ptr;
	}
	
	friend	void* operator new( size_t size, stack_allocator& mem, int count);
	friend	class scoped_mem_stack;

	MEM_PTR	get_top()
	{
		return top_;
	}
protected:
	void	restore(MEM_PTR ptr)
	{
		top_ = ptr;
	}
private:

	MEM_PTR	buffer_;
	MEM_PTR	top_;
	MEM_PTR	bottom_;
};

void* operator new( size_t size, stack_allocator& allocator, int count = 1)
{
	return allocator.alloc(size*count);
};

class scoped_mem_stack
{
public:
	scoped_mem_stack(stack_allocator& allocator):allocator_(allocator)
	{
		backup_top_ = allocator_.get_top();
	}

	~scoped_mem_stack()
	{
		restore();
	}

	void	restore()
	{
		allocator_.restore(backup_top_);
	}
private:
	stack_allocator& allocator_;
	MEM_PTR			 backup_top_;
};

stack_allocator	g_stack_allocator;

struct test_struct
{
	char	buffer[100];
};

void main()
{
	scoped_mem_stack guard(g_stack_allocator);

	MEM_PTR back_ptr = g_stack_allocator.get_top();
	MEM_PTR back_ptr2 = back_ptr;
	assert(back_ptr == g_stack_allocator.get_top());

	void* test_ptr = new(g_stack_allocator) void*;
	back_ptr +=sizeof(void*);
	assert( back_ptr == g_stack_allocator.get_top());

	test_struct*	test_struct_ptr = new(g_stack_allocator) test_struct;
	back_ptr += sizeof(test_struct);
	assert( back_ptr == g_stack_allocator.get_top());

	test_struct**	test_struct_ptr_ptr = new(g_stack_allocator, 5) test_struct*;	
	back_ptr += sizeof(test_struct*)*5;
	assert( back_ptr == g_stack_allocator.get_top());
	guard.restore();

	assert(back_ptr2 == g_stack_allocator.get_top());
}


scoped_lock idiom 과 구현의 방법이 비슷해서 임의로 scoped_mem_stack 이라는 클래스를 사용해 보았다. 
stack을 사용하는 메모리 풀은 흔하게 볼수 있는 예는 아닐것이다. 

stack의 특성상 반드시 할당  받은 순서대로 해제가 되어야 하는 것은 번거로움은 제외 하고라도, 다중 쓰레딩 환경에서도 문제가  될수 있다.

그러나, 위의 구현 예제와 같이 local functin 내에서 일정크기 이상의 메모리 자원이 필요할때 아주 유용하게 사용될수 있을것으로 기대 되며, 매우 빠르다!!!

특히나, stack의 크기(stack allocator가 아닌)를 넘어가는 메모리 자원이 필요할때(게다가 특정 function내에서만 임시로 사용될때) 임시 메모리 버퍼로서 아주 톡톡한 역할을 해 줄수 있을것으로 기대 된다.
allocator의 크기만 유동적으로 조정이 가능하게 구현해 두면, 그냥 막 불러서 사용하면, 해당 function의 scope가 끝나는 시점에서 자동으로(빠르게!!!) 해제가 되니, 이 얼마나 편리하지 않을수가 있을까?

다중 쓰레드 환경에서는 TSS와 같이 사용하면 된다.