-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patheasy_alloc.h
More file actions
125 lines (110 loc) · 2.95 KB
/
easy_alloc.h
File metadata and controls
125 lines (110 loc) · 2.95 KB
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#ifndef __EASY_ALLOC_H__
#define __EASY_ALLOC_H__
typedef struct _EasyAllocNode {
struct _EasyAllocNode *next;
unsigned size;
} EasyAllocNode;
#define EASY_ALLOC_HEAD_SIZE (sizeof(void *) * 2)
#define EASY_ALLOC_NODE_SIZE EASY_ALLOC_HEAD_SIZE * 2
typedef struct _EasyAlloc {
EasyAllocNode head;
} EasyAlloc;
static inline void EasyAllocInit(EasyAlloc *alloc) {
alloc->head.next = 0;
alloc->head.size = 0;
}
static inline unsigned EasyAllocRemaining(EasyAlloc *alloc) {
return alloc->head.size;
}
static inline void _EasyAllocAddBlock(EasyAllocNode *head, EasyAllocNode *block) {
EasyAllocNode *p = head->next;
EasyAllocNode *pp = head;
while (p) {
if (p->size >= block->size) {
break;
}
pp = p;
p = p->next;
}
pp->next = block;
block->next = p;
}
static inline void EasyAllocAddBlock(EasyAlloc *alloc, EasyAllocNode *block) {
alloc->head.size += block->size;
_EasyAllocAddBlock(&alloc->head, block);
}
static inline void EasyAllocAdd(EasyAlloc *alloc, void *ptr, unsigned size) {
EasyAllocNode *p = (EasyAllocNode *)ptr;
p->size = size;
EasyAllocAddBlock(alloc, p);
}
static inline void EasyAllocFree(EasyAlloc *alloc, void *ptr) {
EasyAllocNode *p = (EasyAllocNode *)((char *)ptr - EASY_ALLOC_HEAD_SIZE);
EasyAllocAddBlock(alloc, p);
}
static inline void *EasyAllocAlloc(EasyAlloc *alloc, unsigned size) {
EasyAllocNode *c;
EasyAllocNode *p = alloc->head.next;
EasyAllocNode *pp = &alloc->head;
if (size > 0) {
size += EASY_ALLOC_HEAD_SIZE;
size = (size + EASY_ALLOC_NODE_SIZE - 1) & ~(unsigned)(EASY_ALLOC_NODE_SIZE - 1);
while (p) {
if (p->size < size) {
pp = p;
p = p->next;
} else {
pp->next = p->next;
alloc->head.size -= p->size;
if (p->size >= size + EASY_ALLOC_NODE_SIZE) {
c = (EasyAllocNode *)((char *)p + size);
c->size = p->size - size;
p->size = size;
EasyAllocAddBlock(alloc, c);
}
return (char *)p + EASY_ALLOC_HEAD_SIZE;
}
}
}
return 0;
}
static inline void EasyAllocMerge(EasyAlloc *alloc) {
EasyAllocNode *p = alloc->head.next, *pp = &alloc->head;
EasyAllocNode *p1, *pp1, *lastpp = &alloc->head;
while (p) {
p1 = alloc->head.next;
pp1 = &alloc->head;
while (p1) {
if ((char *)p + p->size == (char *)p1) {
p->size += p1->size;
if (pp != p1) {
pp1->next = p1->next;
pp->next = p->next;
} else {
pp1->next = p->next;
lastpp = pp = pp1;
}
_EasyAllocAddBlock(pp, p);
p = 0;
break;
}
pp1 = p1;
p1 = p1->next;
}
if (p) {
lastpp = pp = p;
p = p->next;
} else {
p = pp->next;
}
}
}
static inline void *EasyAllocMalloc(EasyAlloc *alloc, unsigned size) {
void *r = EasyAllocAlloc(alloc, size);
if (r == NULL) {
EasyAllocMerge(alloc);
r = EasyAllocAlloc(alloc, size);
}
return r;
}
#endif // __EASY_ALLOC_H__