about summary refs log tree commit diff
path: root/src/engine/memheap.c
blob: 0188634fc954fc42488166daa994fcb58a66be0a (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
98
99
100
101
#include "system.h"

typedef struct CHUNK_t
{
	char *memory;
	char *current;
	char *end;
	struct CHUNK_t *next;
} CHUNK;

typedef struct 
{
	CHUNK *current;
} HEAP;

/* how large each chunk should be */
static const int chunksize = 1024*64;

/* allocates a new chunk to be used */
static CHUNK *memheap_newchunk()
{
	CHUNK *chunk;
	char *mem;
	
	/* allocate memory */
	mem = (char*)mem_alloc(sizeof(CHUNK)+chunksize, 1);
	if(!mem)
		return 0x0;

	/* the chunk structure is located in the begining of the chunk */
	/* init it and return the chunk */
	chunk = (CHUNK*)mem;
	chunk->memory = (char*)(chunk+1);
	chunk->current = chunk->memory;
	chunk->end = chunk->memory + chunksize;
	chunk->next = (CHUNK *)0x0;
	return chunk;
}

/******************/
static void *memheap_allocate_from_chunk(CHUNK *chunk, int size)
{
	char *mem;
	
	/* check if we need can fit the allocation */
	if(chunk->current + size >= chunk->end)
		return (void*)0x0;

	/* get memory and move the pointer forward */
	mem = chunk->current;
	chunk->current += size;
	return mem;
}

/* creates a heap */
HEAP *memheap_create()
{
	CHUNK *chunk;
	HEAP *heap;
	
	/* allocate a chunk and allocate the heap structure on that chunk */
	chunk = memheap_newchunk();
	heap = (HEAP *)memheap_allocate_from_chunk(chunk, sizeof(HEAP));
	heap->current = chunk;
	return heap;
}

/* destroys the heap */
void memheap_destroy(HEAP *heap)
{
	CHUNK *chunk = heap->current;
	CHUNK *next;
	
	while(chunk)
	{
		next = chunk->next;
		mem_free(chunk);
		chunk = next;
	}
}

/* */
void *memheap_allocate(HEAP *heap, int size)
{
	char *mem;

	/* try to allocate from current chunk */
	mem = (char *)memheap_allocate_from_chunk(heap->current, size);
	if(!mem)
	{
		/* allocate new chunk and add it to the heap */
		CHUNK *chunk = memheap_newchunk();
		chunk->next = heap->current;
		heap->current = chunk;
		
		/* try to allocate again */
		mem = (char *)memheap_allocate_from_chunk(heap->current, size);
	}
	
	return mem;
}