forked from zerotao/libevhtp
/
evhtp_heap.c
110 lines (79 loc) · 2.21 KB
/
evhtp_heap.c
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <assert.h>
#include <stddef.h>
#include <sys/queue.h>
#include "evhtp-internal.h"
#include "evhtp_heap.h"
struct evhtp_heap_page_s;
typedef struct evhtp_heap_page_s evhtp_heap_page;
struct evhtp_heap_page_s {
SLIST_ENTRY(evhtp_heap_page_s) next;
char data[];
};
struct evhtp_heap_s {
size_t page_size; /* page size */
SLIST_HEAD(, evhtp_heap_page_s) page_list_free;
SLIST_HEAD(, evhtp_heap_page_s) page_list_used;
};
static evhtp_heap_page *
heap_page_new_(evhtp_heap * heap) {
evhtp_heap_page * page;
page = malloc(heap->page_size + sizeof(evhtp_heap_page));
SLIST_INSERT_HEAD(&heap->page_list_free, page, next);
return page;
};
static evhtp_heap *
heap_new_(size_t elts, size_t size) {
evhtp_heap * heap;
if (!(heap = malloc(sizeof(evhtp_heap)))) {
return NULL;
}
heap->page_size = size;
SLIST_INIT(&heap->page_list_free);
SLIST_INIT(&heap->page_list_used);
while (elts-- > 0) {
heap_page_new_(heap);
}
return heap;
}
static void
heap_free_(evhtp_heap * heap, void * d) {
evhtp_heap_page * page;
if (evhtp_unlikely(heap == NULL)) {
return;
}
evhtp_assert(d != NULL);
page = (evhtp_heap_page *)((char *)(d - offsetof(evhtp_heap_page, data)));
evhtp_assert(page != NULL);
evhtp_assert(page->data == d);
SLIST_REMOVE(&heap->page_list_used, page, evhtp_heap_page_s, next);
SLIST_INSERT_HEAD(&heap->page_list_free, page, next);
}
void
evhtp_heap_free(evhtp_heap * heap, void * data) {
return heap_free_(heap, data);
}
static void *
heap_alloc_(evhtp_heap * heap) {
evhtp_heap_page * page;
if (SLIST_EMPTY(&heap->page_list_free)) {
heap_page_new_(heap);
}
page = SLIST_FIRST(&heap->page_list_free);
evhtp_assert(page != NULL);
SLIST_REMOVE(&heap->page_list_free, page, evhtp_heap_page_s, next);
SLIST_INSERT_HEAD(&heap->page_list_used, page, next);
return page->data;
}
void *
evhtp_heap_alloc(evhtp_heap * heap) {
return heap_alloc_(heap);
}
evhtp_heap *
evhtp_heap_new(size_t size, size_t elts) {
return heap_new_(elts, size);
}