blob: 884b743c6a30bb661a5b8ffd6c303814c5a3e620 [file] [log] [blame]
#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);
}