main arena.c
 1/*
 2 Copyright 2015 Michael Pavone
 3 This file is part of BlastEm.
 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
 5*/
 6#include <stdlib.h>
 7#include <stdint.h>
 8#include "arena.h"
 9
10struct arena {
11	void **used_blocks;
12	void **free_blocks;
13
14	size_t used_count;
15	size_t used_storage;
16	size_t free_count;
17	size_t free_storage;
18};
19
20#define DEFAULT_STORAGE_SIZE 8
21
22static arena *current_arena;
23
24arena *get_current_arena()
25{
26	if (!current_arena) {
27		current_arena = calloc(1, sizeof(arena));
28	}
29	return current_arena;
30}
31
32arena *set_current_arena(arena *a)
33{
34	arena *tmp = current_arena;
35	current_arena = a;
36	return tmp;
37}
38
39arena *start_new_arena()
40{
41	arena *tmp = current_arena;
42	current_arena = NULL;
43	return tmp;
44}
45
46void track_block(void *block)
47{
48	arena *cur = get_current_arena();
49	if (cur->used_count == cur->used_storage) {
50		if (cur->used_storage) {
51			cur->used_storage *= 2;
52		} else {
53			cur->used_storage = DEFAULT_STORAGE_SIZE;
54		}
55		cur->used_blocks = realloc(cur->used_blocks, cur->used_storage * sizeof(void *));
56	}
57	cur->used_blocks[cur->used_count++] = block;
58}
59
60void mark_all_free()
61{
62	arena *cur = get_current_arena();
63	if (!cur->free_blocks) {
64		cur->free_blocks = cur->used_blocks;
65		cur->free_storage = cur->used_storage;
66		cur->free_count = cur->used_count;
67		cur->used_count = cur->used_storage = 0;
68		cur->used_blocks = NULL;
69	} else {
70		if (cur->free_storage < cur->used_count + cur->free_count) {
71			cur->free_storage = cur->used_count + cur->free_count;
72			cur->free_blocks = realloc(cur->free_blocks, cur->free_storage * sizeof(void*));
73		}
74		for (; cur->used_count > 0; cur->used_count--)
75		{
76			cur->free_blocks[cur->free_count++] = cur->used_blocks[cur->used_count-1];
77		}
78	}
79}
80
81void *try_alloc_arena()
82{
83	if (!current_arena || !current_arena->free_count) {
84		return NULL;
85	}
86	void *ret = current_arena->free_blocks[--current_arena->free_count];
87	track_block(ret);
88	return ret;
89}