about summary refs log tree commit diff
path: root/src/engine/shared/memheap.cpp
blob: c1c09eaf4b34a2cb0e72c0104e861fb9b0b1913a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com.                */
#include <base/system.h>
#include "memheap.h"

static const int CHUNK_SIZE = 1024*64;

// allocates a new chunk to be used
void CHeap::NewChunk()
{
	CChunk *pChunk;
	char *pMem;

	// allocate memory
	pMem = (char*)mem_alloc(sizeof(CChunk)+CHUNK_SIZE, 1);
	if(!pMem)
		return;

	// the chunk structure is located in the begining of the chunk
	// init it and return the chunk
	pChunk = (CChunk*)pMem;
	pChunk->m_pMemory = (char*)(pChunk+1);
	pChunk->m_pCurrent = pChunk->m_pMemory;
	pChunk->m_pEnd = pChunk->m_pMemory + CHUNK_SIZE;
	pChunk->m_pNext = (CChunk *)0x0;

	pChunk->m_pNext = m_pCurrent;
	m_pCurrent = pChunk;
}

//****************
void *CHeap::AllocateFromChunk(unsigned int Size)
{
	char *pMem;

	// check if we need can fit the allocation
	if(m_pCurrent->m_pCurrent + Size > m_pCurrent->m_pEnd)
		return (void*)0x0;

	// get memory and move the pointer forward
	pMem = m_pCurrent->m_pCurrent;
	m_pCurrent->m_pCurrent += Size;
	return pMem;
}

// creates a heap
CHeap::CHeap()
{
	m_pCurrent = 0x0;
	Reset();
}

CHeap::~CHeap()
{
	Clear();
}

void CHeap::Reset()
{
	Clear();
	NewChunk();
}

// destroys the heap
void CHeap::Clear()
{
	CChunk *pChunk = m_pCurrent;
	CChunk *pNext;

	while(pChunk)
	{
		pNext = pChunk->m_pNext;
		mem_free(pChunk);
		pChunk = pNext;
	}

	m_pCurrent = 0x0;
}

//
void *CHeap::Allocate(unsigned Size)
{
	char *pMem;

	// try to allocate from current chunk
	pMem = (char *)AllocateFromChunk(Size);
	if(!pMem)
	{
		// allocate new chunk and add it to the heap
		NewChunk();

		// try to allocate again
		pMem = (char *)AllocateFromChunk(Size);
	}

	return pMem;
}