Mirai's Miscellaneous Misadventures
M33 / core / allocators.c
1
2
3
4#include <mimimi/allocators.h>
5#include <mimimi/compound-behaviors.h>
6
7struct mimimi_temporary_allocator
8{
9 struct mimimi_allocator *allocator;
10 int count;
11 void **allocated;
12};
13
14static void *mimimi_temporary_allocate(void *data, unsigned int size)
15{
16 struct mimimi_temporary_allocator *temporary_allocator = data;
17 struct mimimi_allocator *allocator = temporary_allocator->allocator;
18
19 void *value = mimimi_allocate(allocator, size);
20
21 temporary_allocator->allocated = mimimi_reallocate(allocator, temporary_allocator->allocated, (temporary_allocator->count + 1) * sizeof *temporary_allocator->allocated);
22 temporary_allocator->allocated[temporary_allocator->count] = value;
23 temporary_allocator->count++;
24
25 return value;
26}
27
28static void *mimimi_temporary_reallocate(void *data, void *value, unsigned int size)
29{
30 struct mimimi_temporary_allocator *temporary_allocator = data;
31 struct mimimi_allocator *allocator = temporary_allocator->allocator;
32
33 if (value == allocator->null)
34 return mimimi_temporary_allocate(data, size);
35
36 int i = 0;
37 while (temporary_allocator->allocated[i] != value) i++;
38
39 value = mimimi_reallocate(allocator, value, size);
40 temporary_allocator->allocated[i] = value;
41
42 return value;
43}
44
45static void mimimi_temporary_deallocate(void *data, void *value)
46{
47 struct mimimi_temporary_allocator *temporary_allocator = data;
48 struct mimimi_allocator *allocator = temporary_allocator->allocator;
49
50 int i = 0;
51 while (temporary_allocator->allocated[i] != value) i++;
52
53 for (int j = i + 1 ; j < temporary_allocator->count ; j++)
54 temporary_allocator->allocated[j - 1] = temporary_allocator->allocated[j];
55
56 temporary_allocator->count--;
57 if (temporary_allocator->count == 0)
58 mimimi_deallocate(allocator, temporary_allocator->allocated),
59 temporary_allocator->allocated = allocator->null;
60 else
61 temporary_allocator->allocated = mimimi_reallocate(allocator, temporary_allocator->allocated, temporary_allocator->count * sizeof *temporary_allocator->allocated);
62
63 mimimi_deallocate(temporary_allocator->allocator, value);
64}
65
66struct mimimi_allocator *mimimi_temporary_allocator(struct mimimi_allocator *allocator)
67{
68 struct mimimi_temporary_allocator *temporary_allocator = mimimi_allocate(allocator, sizeof *temporary_allocator);
69 temporary_allocator->allocator = allocator;
70 temporary_allocator->count = 0;
71 temporary_allocator->allocated = allocator->null;
72
73 struct mimimi_allocator *result = mimimi_allocate(allocator, sizeof *result);
74 result->allocate = &mimimi_temporary_allocate;
75 result->deallocate = &mimimi_temporary_deallocate;
76 result->reallocate = &mimimi_temporary_reallocate;
77 result->null = allocator->null;
78 result->data = temporary_allocator;
79
80 return result;
81}
82
83void mimimi_finish_temporary_allocator(struct mimimi_allocator *result)
84{
85 struct mimimi_temporary_allocator *temporary_allocator = result->data;
86 struct mimimi_allocator *allocator = temporary_allocator->allocator;
87
88 for (int i = 0 ; i < temporary_allocator->count ; i++)
89 mimimi_deallocate(allocator, temporary_allocator->allocated[i]);
90 if (temporary_allocator->count != 0)
91 mimimi_deallocate(allocator, temporary_allocator->allocated);
92 mimimi_deallocate(allocator, temporary_allocator);
93 mimimi_deallocate(allocator, result);
94}
95
96static void mimimi_compound_allocator_finish(void *data)
97{
98 mimimi_finish_temporary_allocator(data);
99}
100
101struct mimimi_allocator *mimimi_compound_allocator(struct mimimi_behavior *compound, struct mimimi_allocator *allocator)
102{
103 struct mimimi_allocator *temporary_allocator = mimimi_temporary_allocator(allocator);
104 mimimi_compound(compound, mimimi_finalizer(temporary_allocator, &mimimi_compound_allocator_finish, allocator));
105 return temporary_allocator;
106}