Created
March 21, 2012 16:32
-
-
Save stbuehler/2149333 to your computer and use it in GitHub Desktop.
custom c++ allocators using glib slice/mallo and mmap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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