add custom slab allocator for stlredblack
This commit is contained in:
parent
0d5c22991d
commit
1708a716e1
6 changed files with 197 additions and 3 deletions
|
@ -47,7 +47,7 @@ ADD_LIBRARY(stasis crc32.c redblack.c tsearchcompat.c lhtable.c concurrentHash.c
|
|||
bufferManager/bufferHash.c replacementPolicy/lru.c
|
||||
replacementPolicy/lruFast.c replacementPolicy/threadsafeWrapper.c replacementPolicy/concurrentWrapper.c
|
||||
util/log2.c util/histogram.c util/hashFunctions.c
|
||||
util/multiset.c
|
||||
stlredblack.cpp)
|
||||
util/multiset.c util/slab.c
|
||||
stlredblack.cpp util/stlslab.cpp)
|
||||
|
||||
INSTALL(TARGETS stasis LIBRARY DESTINATION lib)
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#include <stasis/redblack.h>
|
||||
#include <stdio.h>
|
||||
#undef end
|
||||
#undef try
|
||||
#undef catch
|
||||
#include <stasis/util/stlslab.h>
|
||||
|
||||
extern "C" {
|
||||
typedef int (*c_cmp_t)(const void*, const void*, const void*);
|
||||
|
@ -26,7 +29,7 @@ class MyCompare {
|
|||
MyCompare(c_cmp_t cmp, int dummy) : cmp_(cmp), arg_(NULL) {}
|
||||
};
|
||||
|
||||
typedef std::set<const void*,MyCompare> rb;
|
||||
typedef std::set<const void*,MyCompare, stlslab<const void *> > rb;
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
|
90
src/stasis/util/slab.c
Normal file
90
src/stasis/util/slab.c
Normal file
|
@ -0,0 +1,90 @@
|
|||
#include <stasis/common.h>
|
||||
#include <stasis/util/slab.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* @file A simple (single-threaded) slab allocator
|
||||
*
|
||||
* Created on: Nov 12, 2010
|
||||
* Author: sears
|
||||
*/
|
||||
struct stasis_util_slab_t {
|
||||
byte ** blocks;
|
||||
void * freelist_ptr;
|
||||
uint32_t obj_sz;
|
||||
uint32_t block_sz;
|
||||
uint32_t objs_per_block;
|
||||
uint32_t this_block_count;
|
||||
uint32_t this_block;
|
||||
uint32_t refcount; // the #*%(^!!! stl wants to copy-construct us to %$!! and back, so we need a way to refcount...
|
||||
};
|
||||
/**
|
||||
* Create a slab allocator
|
||||
* @param the size of each object to be allocated
|
||||
* @return a slab allocator. Calling stasis_util_slab_destroy() will deallocate it all-at-once.
|
||||
*/
|
||||
stasis_util_slab_t * stasis_util_slab_create(uint32_t obj_sz, uint32_t block_sz) {
|
||||
stasis_util_slab_t* ret = malloc(sizeof(*ret));
|
||||
|
||||
// printf("slab init: obj siz = %lld, block_sz = %lld\n", (long long)obj_sz, (long long)block_sz);
|
||||
|
||||
ret->blocks = malloc(sizeof(ret->blocks[0]));
|
||||
ret->blocks[0] = malloc(block_sz);
|
||||
ret->freelist_ptr = 0;
|
||||
|
||||
ret->obj_sz = obj_sz;
|
||||
ret->block_sz = block_sz;
|
||||
ret->objs_per_block = block_sz / obj_sz;
|
||||
|
||||
ret->this_block_count = 0;
|
||||
ret->this_block = 0;
|
||||
ret->refcount = 1;
|
||||
return ret;
|
||||
}
|
||||
void stasis_util_slab_ref(stasis_util_slab_t * slab) {
|
||||
(slab->refcount)++;
|
||||
}
|
||||
void stasis_util_slab_destroy(stasis_util_slab_t * slab) {
|
||||
(slab->refcount)--;
|
||||
if(!slab->refcount) {
|
||||
for(int i = 0; i <= slab->this_block; i++) {
|
||||
free(slab->blocks[i]);
|
||||
}
|
||||
free(slab->blocks);
|
||||
fprintf(stderr, "Deallocated slab (obj_sz = %lld). Was using %lld bytes\n",
|
||||
(long long) (uint64_t)slab->obj_sz,
|
||||
(long long int)
|
||||
((uint64_t)slab->this_block + 1) * (uint64_t)slab->block_sz);
|
||||
free(slab);
|
||||
}
|
||||
}
|
||||
// XXX get rid of multiplications! Store next free byte instead of obj count!
|
||||
void* stasis_util_slab_malloc(stasis_util_slab_t * slab) {
|
||||
if(slab->freelist_ptr) {
|
||||
void * ret = slab->freelist_ptr;
|
||||
slab->freelist_ptr = *(void**)slab->freelist_ptr;
|
||||
assert(ret);
|
||||
// printf("ALLOC %llx\n", (long long) ret);
|
||||
return ret;
|
||||
} else if(slab->this_block_count == slab->objs_per_block) {
|
||||
(slab->this_block_count) = 0;
|
||||
(slab->this_block) ++;
|
||||
slab->blocks = realloc(slab->blocks, (slab->this_block+1) * sizeof(slab->blocks[0]));
|
||||
assert(slab->blocks);
|
||||
slab->blocks[slab->this_block] = malloc(slab->block_sz);
|
||||
assert(slab->blocks[slab->this_block]);
|
||||
}
|
||||
slab->this_block_count ++;
|
||||
void * ret = (void*) &(slab->blocks[slab->this_block][(slab->this_block_count-1) * slab->obj_sz]);
|
||||
assert(ret);
|
||||
// printf("ALLOC %llx\n", (long long) ret);
|
||||
return ret;
|
||||
}
|
||||
void stasis_util_slab_free(stasis_util_slab_t * slab, void * ptr) {
|
||||
// printf("FREE %llx\n", (long long) ptr);
|
||||
assert(ptr);
|
||||
*((void**)ptr) = slab->freelist_ptr;
|
||||
slab->freelist_ptr = ptr;
|
||||
}
|
||||
|
8
src/stasis/util/stlslab.cpp
Normal file
8
src/stasis/util/stlslab.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* stlslab.cpp
|
||||
*
|
||||
* Created on: Nov 12, 2010
|
||||
* Author: sears
|
||||
*/
|
||||
|
||||
#include <stasis/util/stlslab.h>
|
24
stasis/util/slab.h
Normal file
24
stasis/util/slab.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* slab.h
|
||||
*
|
||||
* Created on: Nov 12, 2010
|
||||
* Author: sears
|
||||
*/
|
||||
|
||||
#ifndef SLAB_H_
|
||||
#define SLAB_H_
|
||||
|
||||
#include <stasis/common.h>
|
||||
|
||||
BEGIN_C_DECLS
|
||||
|
||||
typedef struct stasis_util_slab_t stasis_util_slab_t;
|
||||
stasis_util_slab_t * stasis_util_slab_create(uint32_t obj_sz, uint32_t block_sz);
|
||||
void stasis_util_slab_ref(stasis_util_slab_t * slab);
|
||||
void stasis_util_slab_destroy(stasis_util_slab_t * slab);
|
||||
void* stasis_util_slab_malloc(stasis_util_slab_t * slab);
|
||||
void stasis_util_slab_free(stasis_util_slab_t * slab, void * ptr);
|
||||
|
||||
END_C_DECLS
|
||||
|
||||
#endif /* SLAB_H_ */
|
69
stasis/util/stlslab.h
Normal file
69
stasis/util/stlslab.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* stlslab.h
|
||||
*
|
||||
* Created on: Nov 12, 2010
|
||||
* Author: sears
|
||||
*/
|
||||
|
||||
#ifndef STLSLAB_H_
|
||||
#define STLSLAB_H_
|
||||
#include <algorithm>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stasis/util/slab.h>
|
||||
#include <assert.h>
|
||||
|
||||
template <class T>
|
||||
class stlslab {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef T& reference;
|
||||
typedef const T* const_pointer;
|
||||
typedef const T& const_reference;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
|
||||
stlslab ( ) throw() {
|
||||
alloc = stasis_util_slab_create(sizeof(T), 65536);
|
||||
}
|
||||
stlslab ( const stlslab& s) throw() {
|
||||
printf("Expensive!!\n");
|
||||
alloc = stasis_util_slab_create(sizeof(T), /*sizeof(U),*/ 65536);
|
||||
// alloc = s.alloc;
|
||||
// assert(alloc);
|
||||
stasis_util_slab_ref(alloc);
|
||||
}
|
||||
template <class U>
|
||||
stlslab( const stlslab<U>& s) throw() {
|
||||
// printf("sizeof U %lld\n", (long long)sizeof(U));
|
||||
alloc = s.alloc;
|
||||
|
||||
//assert(alloc);
|
||||
stasis_util_slab_ref(alloc);
|
||||
}
|
||||
~stlslab () {
|
||||
stasis_util_slab_destroy(alloc);
|
||||
}
|
||||
pointer address ( reference x ) const { return &x; }
|
||||
const_pointer address ( const_reference x ) const { return &x; }
|
||||
|
||||
template<typename _Tp1>
|
||||
struct rebind
|
||||
{ typedef stlslab<_Tp1> other; };
|
||||
|
||||
pointer allocate (size_type n, stlslab::const_pointer hint=0) {
|
||||
assert(n == 1);
|
||||
return (T*) stasis_util_slab_malloc(alloc);
|
||||
}
|
||||
void deallocate (pointer p, size_type n) {
|
||||
assert(n == 1);
|
||||
stasis_util_slab_free(alloc, p);
|
||||
}
|
||||
size_type max_size() const throw() { return 1; }
|
||||
void construct ( pointer p, const_reference val ) { new ((void*)p) T (val); }
|
||||
void destroy (pointer p) {((T*)p)->~T(); }
|
||||
stasis_util_slab_t * alloc;
|
||||
};
|
||||
|
||||
#endif /* STLSLAB_H_ */
|
Loading…
Reference in a new issue