diff --git a/include/tscore/Allocator.h b/include/tscore/Allocator.h index c03f996ab84..55b1bbcb73f 100644 --- a/include/tscore/Allocator.h +++ b/include/tscore/Allocator.h @@ -39,8 +39,10 @@ #pragma once -#include #include +#include +#include +#include #include "tscore/ink_queue.h" #include "tscore/ink_defs.h" #include "tscore/ink_resource.h" @@ -113,24 +115,20 @@ class Allocator }; /** - Allocator for Class objects. It uses a prototype object to do - fast initialization. Prototype of the template class is created - when the fast allocator is created. This is instantiated with - default (no argument) constructor. Constructor is not called for - the allocated objects. Instead, the prototype is just memory - copied onto the new objects. This is done for performance reasons. + Allocator for Class objects. */ -template class ClassAllocator : public Allocator +template class ClassAllocator : public Allocator { public: - /** Allocates objects of the templated type. */ + /** Allocates objects of the templated type. Arguments are forwarded to the constructor for the object. */ + template C * - alloc() + alloc(Args &&... args) { void *ptr = ink_freelist_new(this->fl); - memcpy(ptr, (void *)&this->proto.typeObject, sizeof(C)); + ::new (ptr) C(std::forward(args)...); return (C *)ptr; } @@ -142,6 +140,9 @@ template class ClassAllocator : public Allocator void free(C *ptr) { + if (Destruct_on_free) { + ptr->~C(); + } ink_freelist_free(this->fl, ptr); } @@ -152,7 +153,7 @@ template class ClassAllocator : public Allocator @param tail pointer to be freed. @param num_item of blocks to be freed. */ - void + std::enable_if_t free_bulk(C *head, C *tail, size_t num_item) { ink_freelist_free_bulk(this->fl, head, tail, num_item); @@ -165,7 +166,7 @@ template class ClassAllocator : public Allocator void * alloc_void() { - return (void *)alloc(); + return alloc(); } /** @@ -174,7 +175,7 @@ template class ClassAllocator : public Allocator @param ptr pointer to be freed. */ - void + std::enable_if_t free_void(void *ptr) { free((C *)ptr); @@ -188,7 +189,7 @@ template class ClassAllocator : public Allocator @param tail pointer to be freed. @param num_item of blocks. */ - void + std::enable_if_t free_void_bulk(void *head, void *tail, size_t num_item) { free_bulk((C *)head, (C *)tail, num_item); @@ -203,21 +204,15 @@ template class ClassAllocator : public Allocator */ ClassAllocator(const char *name, unsigned int chunk_size = 128, unsigned int alignment = 16) { - ::new ((void *)&proto.typeObject) C(); ink_freelist_init(&this->fl, name, RND16(sizeof(C)), chunk_size, RND16(alignment)); } - - struct { - uint8_t typeObject[sizeof(C)]; - int64_t space_holder = 0; - } proto; }; -template class TrackerClassAllocator : public ClassAllocator +template class TrackerClassAllocator : public ClassAllocator { public: TrackerClassAllocator(const char *name, unsigned int chunk_size = 128, unsigned int alignment = 16) - : ClassAllocator(name, chunk_size, alignment), allocations(0), trackerLock(PTHREAD_MUTEX_INITIALIZER) + : ClassAllocator(name, chunk_size, alignment), allocations(0), trackerLock(PTHREAD_MUTEX_INITIALIZER) { } @@ -226,7 +221,7 @@ template class TrackerClassAllocator : public ClassAllocator { void *callstack[3]; int frames = backtrace(callstack, 3); - C *ptr = ClassAllocator::alloc(); + C *ptr = ClassAllocator::alloc(); const void *symbol = nullptr; if (frames == 3 && callstack[2] != nullptr) { @@ -252,7 +247,7 @@ template class TrackerClassAllocator : public ClassAllocator reverse_lookup.erase(it); } ink_mutex_release(&trackerLock); - ClassAllocator::free(ptr); + ClassAllocator::free(ptr); } private: diff --git a/iocore/eventsystem/I_ProxyAllocator.h b/iocore/eventsystem/I_ProxyAllocator.h index a5edd125fd0..b19baa6b8a4 100644 --- a/iocore/eventsystem/I_ProxyAllocator.h +++ b/iocore/eventsystem/I_ProxyAllocator.h @@ -30,6 +30,9 @@ *****************************************************************************/ #pragma once +#include +#include + #include "tscore/ink_platform.h" class EThread; @@ -45,32 +48,27 @@ struct ProxyAllocator { ProxyAllocator() {} }; -template +template inline C * -thread_alloc(ClassAllocator &a, ProxyAllocator &l) +thread_alloc(ClassAllocator &a, ProxyAllocator &l, Args &&... args) { if (!cmd_disable_pfreelist && l.freelist) { - C *v = (C *)l.freelist; - l.freelist = *(C **)l.freelist; + void *v = l.freelist; + l.freelist = *reinterpret_cast(l.freelist); --(l.allocated); - *(void **)v = *(void **)&a.proto.typeObject; - return v; + ::new (v) C(std::forward(args)...); + return static_cast(v); } - return a.alloc(); + return a.alloc(std::forward(args)...); } -template +// Redundant it seems. +// +template inline C * -thread_alloc_init(ClassAllocator &a, ProxyAllocator &l) +thread_alloc_init(ClassAllocator &a, ProxyAllocator &l, Args &&... args) { - if (!cmd_disable_pfreelist && l.freelist) { - C *v = (C *)l.freelist; - l.freelist = *(C **)l.freelist; - --(l.allocated); - memcpy((void *)v, (void *)&a.proto.typeObject, sizeof(C)); - return v; - } - return a.alloc(); + return thread_alloc(a, l, std::forward(args)...); } template