/** * @file fastalloc.h * * Lightweight specialized memory allocator for lots of equally-sized objects. * * @experimental */ #ifndef COL_FASTALLOC_H #define COL_FASTALLOC_H #include "base/base.h" /** * Fast memory allocator for identically sized chunks. * * This maintains a free list and never frees anything. */ template class SlabAllocator { private: // TODO: what if we want to free the entire thing? static char *freelist_; //static char *slab_list_; public: static void AllocSlab(); static char *Alloc() { if (unlikely(freelist_ == NULL)) { AllocSlab(); } char *item = freelist_; freelist_ = *reinterpret_cast(freelist_); return item; } static void Free(char *item) { *reinterpret_cast(item) = freelist_; freelist_ = item; } }; template void SlabAllocator::AllocSlab() { int slab_items = 128; // TODO: hard-coded constant size_t real_item_size = stride_align(item_size, char *); size_t size = real_item_size * slab_items + sizeof(char *); char *slab = mem::Alloc(size); // slab_items must be at least 2 *reinterpret_cast(slab) = freelist_; --slab_items; do { char *prev = slab; slab += real_item_size; *reinterpret_cast(slab) = prev; } while (--slab_items); freelist_ = slab; //slab += real_item_size; // //*reinterpret_cast(slab) = slab_list_; //slab_list_ = slab; } template char *SlabAllocator::freelist_ = 0; /** * A very lightweight replacement for new for allocating lots of objects * of the same type. * * @experimental * * This allocator has zero space overhead and only a marginal per-allocation * overhead. It is useful for cases where you need to allocate lots * of pointers to the same type of object and might need to free a lot * too. It is not at all useful for arrays. * * Syntax is slightly different from new/delete: * * @code * MyClass *ptr1 = fast_new(MyClass); * MyClass *ptr2 = fast_new(MyClass)(constructor, parameters, go, here); * @endcode * * @param T the type being allocated */ #define fast_new(T) new(SlabAllocator::Alloc()) T /** * Delete operator for fast_new. * * @experimental * * @code * fast_delete(ptr); * @endcode * * @param ptr the pointer to destruct and free */ template inline void fast_delete(T *ptr) { ptr->~T(); SlabAllocator::Free(reinterpret_cast(ptr)); } #endif