Skip to content

Instantly share code, notes, and snippets.

@stbuehler
Created March 21, 2012 16:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stbuehler/2149333 to your computer and use it in GitHub Desktop.
Save stbuehler/2149333 to your computer and use it in GitHub Desktop.
custom c++ allocators using glib slice/mallo and mmap
// g++ -O3 -Wall `pkg-config --cflags --libs glib-2.0` cppallocs.cpp -o cppallocs
#include <new>
#include <glib.h>
#include <sys/mman.h>
// Use different allocators depending on size, so we need to remember the size
// One could add other members,like some magic data to check the allocs/frees
struct memblock {
std::size_t size;
char buf[]; // actual data
};
static inline void* my_alloc(std::size_t size) {
memblock *block = 0;
size += sizeof(memblock);
if (size <= 128) {
// slice allocator: put objects of the same size together in an "array"
block = reinterpret_cast<memblock*>(g_slice_alloc(size));
} else if (size < 4096) {
// standard malloc
block = reinterpret_cast<memblock*>(g_malloc(size));
} else {
// larger than usual PAGESIZE, so mmap doesn't waste too much (always allocates multiples of PAGESIZE)
void *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
if (MAP_FAILED != ptr) block = reinterpret_cast<memblock*>(ptr);
}
if (0 == block) return 0;
block->size = size;
return block->buf;
}
static inline void my_free(void *ptr) {
memblock *block = reinterpret_cast<memblock*>(reinterpret_cast<char*>(ptr) - sizeof(memblock));
std::size_t size = block->size;
if (size < 128) {
g_slice_free1(size, block);
} else if (size < 4096) {
g_free(block);
} else {
munmap(block, size);
}
}
void* operator new (std::size_t size) throw (std::bad_alloc) {
void *p = my_alloc(size);
if (0 == p) throw std::bad_alloc();
return p;
}
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw() {
return my_alloc(size);
}
void* operator new[] (std::size_t size) throw (std::bad_alloc) {
void *p = my_alloc(size);
if (0 == p) throw std::bad_alloc();
return p;
}
void* operator new[] (std::size_t size, const std::nothrow_t& nothrow_constant) throw() {
return my_alloc(size);
}
void operator delete (void* ptr) throw () {
my_free(ptr);
}
void operator delete (void* ptr, const std::nothrow_t& nothrow_constant) throw() {
my_free(ptr);
}
void operator delete[] (void* ptr) throw () {
my_free(ptr);
}
void operator delete[] (void* ptr, const std::nothrow_t& nothrow_constant) throw() {
my_free(ptr);
}
class A {
public:
int x, y;
};
int main() {
A *a = new A[5000];
delete[] a;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment