Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 20 additions & 25 deletions include/tscore/Allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@

#pragma once

#include <new>
#include <cstdlib>
#include <new>
#include <type_traits>
#include <utility>
#include "tscore/ink_queue.h"
#include "tscore/ink_defs.h"
#include "tscore/ink_resource.h"
Expand Down Expand Up @@ -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 C> class ClassAllocator : public Allocator
template <class C, bool Destruct_on_free = false> 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 <typename... Args>
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>(args)...);
return (C *)ptr;
}

Expand All @@ -142,6 +140,9 @@ template <class C> class ClassAllocator : public Allocator
void
free(C *ptr)
{
if (Destruct_on_free) {
ptr->~C();
}
ink_freelist_free(this->fl, ptr);
}

Expand All @@ -152,7 +153,7 @@ template <class C> class ClassAllocator : public Allocator
@param tail pointer to be freed.
@param num_item of blocks to be freed.
*/
void
std::enable_if_t<!Destruct_on_free, void>
free_bulk(C *head, C *tail, size_t num_item)
{
ink_freelist_free_bulk(this->fl, head, tail, num_item);
Expand All @@ -165,7 +166,7 @@ template <class C> class ClassAllocator : public Allocator
void *
alloc_void()
{
return (void *)alloc();
return alloc();
}

/**
Expand All @@ -174,7 +175,7 @@ template <class C> class ClassAllocator : public Allocator

@param ptr pointer to be freed.
*/
void
std::enable_if_t<!Destruct_on_free, void>
free_void(void *ptr)
{
free((C *)ptr);
Expand All @@ -188,7 +189,7 @@ template <class C> class ClassAllocator : public Allocator
@param tail pointer to be freed.
@param num_item of blocks.
*/
void
std::enable_if_t<!Destruct_on_free, void>
free_void_bulk(void *head, void *tail, size_t num_item)
{
free_bulk((C *)head, (C *)tail, num_item);
Expand All @@ -203,21 +204,15 @@ template <class C> 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 C> class TrackerClassAllocator : public ClassAllocator<C>
template <class C, bool Destruct_on_free = false> class TrackerClassAllocator : public ClassAllocator<C, Destruct_on_free>
{
public:
TrackerClassAllocator(const char *name, unsigned int chunk_size = 128, unsigned int alignment = 16)
: ClassAllocator<C>(name, chunk_size, alignment), allocations(0), trackerLock(PTHREAD_MUTEX_INITIALIZER)
: ClassAllocator<C, Destruct_on_free>(name, chunk_size, alignment), allocations(0), trackerLock(PTHREAD_MUTEX_INITIALIZER)
{
}

Expand All @@ -226,7 +221,7 @@ template <class C> class TrackerClassAllocator : public ClassAllocator<C>
{
void *callstack[3];
int frames = backtrace(callstack, 3);
C *ptr = ClassAllocator<C>::alloc();
C *ptr = ClassAllocator<C, Destruct_on_free>::alloc();

const void *symbol = nullptr;
if (frames == 3 && callstack[2] != nullptr) {
Expand All @@ -252,7 +247,7 @@ template <class C> class TrackerClassAllocator : public ClassAllocator<C>
reverse_lookup.erase(it);
}
ink_mutex_release(&trackerLock);
ClassAllocator<C>::free(ptr);
ClassAllocator<C, Destruct_on_free>::free(ptr);
}

private:
Expand Down
32 changes: 15 additions & 17 deletions iocore/eventsystem/I_ProxyAllocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
*****************************************************************************/
#pragma once

#include <new>
#include <utility>

#include "tscore/ink_platform.h"

class EThread;
Expand All @@ -45,32 +48,27 @@ struct ProxyAllocator {
ProxyAllocator() {}
};

template <class C>
template <class C, typename... Args>
inline C *
thread_alloc(ClassAllocator<C> &a, ProxyAllocator &l)
thread_alloc(ClassAllocator<C> &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<void **>(l.freelist);
--(l.allocated);
*(void **)v = *(void **)&a.proto.typeObject;
return v;
::new (v) C(std::forward<Args>(args)...);
return static_cast<C *>(v);
}
return a.alloc();
return a.alloc(std::forward<Args>(args)...);
}

template <class C>
// Redundant it seems.
//
template <class C, typename... Args>
inline C *
thread_alloc_init(ClassAllocator<C> &a, ProxyAllocator &l)
thread_alloc_init(ClassAllocator<C> &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<C, Args...>(a, l, std::forward<Args>(args)...);
}

template <class C>
Expand Down