#include "pool.hpp"
HOOK(PRE_IO, HOOK_PRIO_MID) {
int slot = 0;
for (size_t s = SLAB_POOL_MIN; slot < SLAB_POOL_NUM; slot++, s*=2) {
log(debug, "slab pool %d/%d: %zu bytes", slot+1, SLAB_POOL_NUM, s);
}
}
SlabPool slab_pool;
SlabPool::SlabPool() {
memset(slots, 0, sizeof(slots));
}
SlabPool::~SlabPool() {
for (int i = 0; i<SLAB_POOL_NUM; i++) {
while (slots[i]) {
slab_node_t* node = slots[i];
slots[i] = node->next;
free(node);
}
}
}
void* SlabPool::pop(size_t len) {
assert(len);
stats_inc(spool_allocs);
#if MAX_POOL_SPARE == 0
#ifndef DEBUG
MESSAGE(slab pool disabled)
#endif
return malloc(len);
#endif
len += sizeof(slab_node_t);
int slot = 0;
for (size_t s = SLAB_POOL_MIN; slot < SLAB_POOL_NUM; slot++, s*=2) {
if (s >= len) break;
}
slab_node_t* rv;
if (slot < SLAB_POOL_NUM && slots[slot]) {
rv = slots[slot];
slots[slot] = rv->next;
stats_inc(spool_hits);
} else {
rv = (slab_node_t*)malloc(len);
rv->slot = slot;
}
return (void*)((char*)rv + sizeof(slab_node_t));
}
char* SlabPool::dup(const char* s, size_t l) {
assert(l);
char* rv = (char*)pop(l+1);
memcpy(rv, s, l);
rv[l] = '\0';
return rv;
}
void SlabPool::push(void* p) {
#if MAX_POOL_SPARE == 0
free(p);
return;
#endif
if (!p) return;
slab_node_t* node = (slab_node_t*)((char*)p - sizeof(slab_node_t));
if (unlikely(node->slot >= SLAB_POOL_MIN)) {
free(node);
} else {
// TODO: check if allowed wrt. MAX_POOL_SPARE
node->next = slots[node->slot];
slots[node->slot] = node;
}
}
TEST(refcount) {
RefCount<int>* ref = new RefCount<int>(42);
ref->inc();
int* foo = &ref->val;
ref->dec();
int bar = ref->val;
TEST_ASSERT(*foo == bar && *foo == 42); // pretty pointless
ref->dec();
return true; // this test relies on valgrind rather on correctness checks
}