4141
4242#include < new>
4343#include < cstdlib>
44- #include < utility>
4544#include " tscore/ink_queue.h"
4645#include " tscore/ink_defs.h"
4746#include " tscore/ink_resource.h"
@@ -109,39 +108,29 @@ class Allocator
109108 ink_freelist_madvise_init (&this ->fl , name, element_size, chunk_size, alignment, advice);
110109 }
111110
112- // Dummies
113- void
114- destroy_if_enabled (void *)
115- {
116- }
117- Allocator &
118- raw ()
119- {
120- return *this ;
121- }
122-
123111protected:
124112 InkFreeList *fl;
125113};
126114
127115/* *
128- Allocator for Class objects.
116+ Allocator for Class objects. It uses a prototype object to do
117+ fast initialization. Prototype of the template class is created
118+ when the fast allocator is created. This is instantiated with
119+ default (no argument) constructor. Constructor is not called for
120+ the allocated objects. Instead, the prototype is just memory
121+ copied onto the new objects. This is done for performance reasons.
129122
130123*/
131- template <class C , bool Destruct_on_free_ = false > class ClassAllocator : private Allocator
124+ template <class C > class ClassAllocator : public Allocator
132125{
133126public:
134- using Value_type = C;
135- static bool const Destruct_on_free = Destruct_on_free_;
136-
137- /* * Allocates objects of the templated type. Arguments are forwarded to the constructor for the object. */
138- template <typename ... Args>
127+ /* * Allocates objects of the templated type. */
139128 C *
140- alloc (Args &&... args )
129+ alloc ()
141130 {
142131 void *ptr = ink_freelist_new (this ->fl );
143132
144- :: new (ptr) C (std::forward<Args>(args)... );
133+ memcpy (ptr, ( void *)& this -> proto . typeObject , sizeof (C) );
145134 return (C *)ptr;
146135 }
147136
@@ -153,47 +142,82 @@ template <class C, bool Destruct_on_free_ = false> class ClassAllocator : privat
153142 void
154143 free (C *ptr)
155144 {
156- destroy_if_enabled (ptr);
157-
158145 ink_freelist_free (this ->fl , ptr);
159146 }
160147
161148 /* *
162- Create a new class specific ClassAllocator .
149+ Deallocates objects of the templated type .
163150
164- @param name some identifying name, used for mem tracking purposes.
165- @param chunk_size number of units to be allocated if free pool is empty.
166- @param alignment of objects must be a power of 2.
151+ @param head pointer to be freed.
152+ @param tail pointer to be freed.
153+ @param num_item of blocks to be freed.
154+ */
155+ void
156+ free_bulk (C *head, C *tail, size_t num_item)
157+ {
158+ ink_freelist_free_bulk (this ->fl , head, tail, num_item);
159+ }
160+
161+ /* *
162+ Allocate objects of the templated type via the inherited interface
163+ using void pointers.
167164 */
168- ClassAllocator (const char *name, unsigned int chunk_size = 128 , unsigned int alignment = 16 )
165+ void *
166+ alloc_void ()
169167 {
170- ink_freelist_init (& this -> fl , name, RND16 ( sizeof (C)), chunk_size, RND16 (alignment) );
168+ return ( void *) alloc ( );
171169 }
172170
173- Allocator &
174- raw ()
171+ /* *
172+ Deallocate objects of the templated type via the inherited
173+ interface using void pointers.
174+
175+ @param ptr pointer to be freed.
176+ */
177+ void
178+ free_void (void *ptr)
175179 {
176- return * this ;
180+ free ((C *)ptr) ;
177181 }
178182
183+ /* *
184+ Deallocate objects of the templated type via the inherited
185+ interface using void pointers.
186+
187+ @param head pointer to be freed.
188+ @param tail pointer to be freed.
189+ @param num_item of blocks.
190+ */
179191 void
180- destroy_if_enabled (C *ptr )
192+ free_void_bulk ( void *head, void *tail, size_t num_item )
181193 {
182- if (Destruct_on_free) {
183- ptr->~C ();
184- }
194+ free_bulk ((C *)head, (C *)tail, num_item);
195+ }
196+
197+ /* *
198+ Create a new class specific ClassAllocator.
199+
200+ @param name some identifying name, used for mem tracking purposes.
201+ @param chunk_size number of units to be allocated if free pool is empty.
202+ @param alignment of objects must be a power of 2.
203+ */
204+ ClassAllocator (const char *name, unsigned int chunk_size = 128 , unsigned int alignment = 16 )
205+ {
206+ ::new ((void *)&proto.typeObject ) C ();
207+ ink_freelist_init (&this ->fl , name, RND16 (sizeof (C)), chunk_size, RND16 (alignment));
185208 }
186209
187- // Ensure that C is big enough to hold a void pointer (when it's stored in the free list as raw memory).
188- //
189- static_assert (sizeof (C) >= sizeof (void *), " Can not allocate instances of this class using ClassAllocator" );
210+ struct {
211+ uint8_t typeObject[sizeof (C)];
212+ int64_t space_holder = 0 ;
213+ } proto;
190214};
191215
192- template <class C , bool Destruct_on_free = false > class TrackerClassAllocator : public ClassAllocator <C, Destruct_on_free >
216+ template <class C > class TrackerClassAllocator : public ClassAllocator <C>
193217{
194218public:
195219 TrackerClassAllocator (const char *name, unsigned int chunk_size = 128 , unsigned int alignment = 16 )
196- : ClassAllocator<C, Destruct_on_free >(name, chunk_size, alignment), allocations(0 ), trackerLock(PTHREAD_MUTEX_INITIALIZER)
220+ : ClassAllocator<C>(name, chunk_size, alignment), allocations(0 ), trackerLock(PTHREAD_MUTEX_INITIALIZER)
197221 {
198222 }
199223
@@ -202,7 +226,7 @@ template <class C, bool Destruct_on_free = false> class TrackerClassAllocator :
202226 {
203227 void *callstack[3 ];
204228 int frames = backtrace (callstack, 3 );
205- C *ptr = ClassAllocator<C, Destruct_on_free >::alloc ();
229+ C *ptr = ClassAllocator<C>::alloc ();
206230
207231 const void *symbol = nullptr ;
208232 if (frames == 3 && callstack[2 ] != nullptr ) {
@@ -228,7 +252,7 @@ template <class C, bool Destruct_on_free = false> class TrackerClassAllocator :
228252 reverse_lookup.erase (it);
229253 }
230254 ink_mutex_release (&trackerLock);
231- ClassAllocator<C, Destruct_on_free >::free (ptr);
255+ ClassAllocator<C>::free (ptr);
232256 }
233257
234258private:
0 commit comments