00001 /** @file 00002 00003 Fast-Allocators 00004 00005 @section license License 00006 00007 Licensed to the Apache Software Foundation (ASF) under one 00008 or more contributor license agreements. See the NOTICE file 00009 distributed with this work for additional information 00010 regarding copyright ownership. The ASF licenses this file 00011 to you under the Apache License, Version 2.0 (the 00012 "License"); you may not use this file except in compliance 00013 with the License. You may obtain a copy of the License at 00014 00015 http://www.apache.org/licenses/LICENSE-2.0 00016 00017 Unless required by applicable law or agreed to in writing, software 00018 distributed under the License is distributed on an "AS IS" BASIS, 00019 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00020 See the License for the specific language governing permissions and 00021 limitations under the License. 00022 00023 Provides three classes 00024 - Allocator for allocating memory blocks of fixed size 00025 - ClassAllocator for allocating objects 00026 - SpaceClassAllocator for allocating sparce objects (most members uninitialized) 00027 00028 These class provides a efficient way for handling dynamic allocation. 00029 The fast allocator maintains its own freepool of objects from 00030 which it doles out object. Allocated objects when freed go back 00031 to the free pool. 00032 00033 @note Fast allocators could accumulate a lot of objects in the 00034 free pool as a result of bursty demand. Memory used by the objects 00035 in the free pool never gets freed even if the freelist grows very 00036 large. 00037 00038 */ 00039 00040 #ifndef _Allocator_h_ 00041 #define _Allocator_h_ 00042 00043 #include <stdlib.h> 00044 #include "ink_queue.h" 00045 #include "ink_defs.h" 00046 #include "ink_resource.h" 00047 00048 #define RND16(_x) (((_x)+15)&~15) 00049 00050 /** Allocator for fixed size memory blocks. */ 00051 class Allocator 00052 { 00053 public: 00054 /** 00055 Allocate a block of memory (size specified during construction 00056 of Allocator. 00057 */ 00058 void * 00059 alloc_void() 00060 { 00061 return ink_freelist_new(this->fl); 00062 } 00063 00064 /** Deallocate a block of memory allocated by the Allocator. */ 00065 void 00066 free_void(void *ptr) 00067 { 00068 ink_freelist_free(this->fl, ptr); 00069 } 00070 00071 Allocator() 00072 { 00073 fl = NULL; 00074 } 00075 00076 /** 00077 Creates a new allocator. 00078 00079 @param name identification tag used for mem tracking . 00080 @param element_size size of memory blocks to be allocated. 00081 @param chunk_size number of units to be allocated if free pool is empty. 00082 @param alignment of objects must be a power of 2. 00083 */ 00084 Allocator(const char *name, unsigned int element_size, 00085 unsigned int chunk_size = 128, unsigned int alignment = 8) 00086 { 00087 ink_freelist_init(&fl, name, element_size, chunk_size, alignment); 00088 } 00089 00090 /** Re-initialize the parameters of the allocator. */ 00091 void 00092 re_init(const char *name, unsigned int element_size, 00093 unsigned int chunk_size, unsigned int alignment) 00094 { 00095 ink_freelist_init(&this->fl, name, element_size, chunk_size, alignment); 00096 } 00097 00098 protected: 00099 InkFreeList *fl; 00100 }; 00101 00102 /** 00103 Allocator for Class objects. It uses a prototype object to do 00104 fast initialization. Prototype of the template class is created 00105 when the fast allocator is created. This is instantiated with 00106 default (no argument) constructor. Constructor is not called for 00107 the allocated objects. Instead, the prototype is just memory 00108 copied onto the new objects. This is done for performance reasons. 00109 00110 */ 00111 template<class C> class ClassAllocator: public Allocator { 00112 public: 00113 /** Allocates objects of the templated type. */ 00114 C* 00115 alloc() 00116 { 00117 void *ptr = ink_freelist_new(this->fl); 00118 00119 memcpy(ptr, (void *)&this->proto.typeObject, sizeof(C)); 00120 return (C *) ptr; 00121 } 00122 00123 /** 00124 Deallocates objects of the templated type. 00125 00126 @param ptr pointer to be freed. 00127 */ 00128 void 00129 free(C * ptr) 00130 { 00131 ink_freelist_free(this->fl, ptr); 00132 } 00133 00134 /** 00135 Allocate objects of the templated type via the inherited interface 00136 using void pointers. 00137 */ 00138 void* 00139 alloc_void() 00140 { 00141 return (void *) alloc(); 00142 } 00143 00144 /** 00145 Deallocate objects of the templated type via the inherited 00146 interface using void pointers. 00147 00148 @param ptr pointer to be freed. 00149 */ 00150 void 00151 free_void(void *ptr) 00152 { 00153 free((C *) ptr); 00154 } 00155 00156 /** 00157 Create a new class specific ClassAllocator. 00158 00159 @param name some identifying name, used for mem tracking purposes. 00160 @param chunk_size number of units to be allocated if free pool is empty. 00161 @param alignment of objects must be a power of 2. 00162 */ 00163 ClassAllocator(const char *name, unsigned int chunk_size = 128, 00164 unsigned int alignment = 16) 00165 { 00166 ink_freelist_init(&this->fl, name, RND16(sizeof(C)), chunk_size, RND16(alignment)); 00167 } 00168 00169 struct 00170 { 00171 C typeObject; 00172 int64_t space_holder; 00173 } proto; 00174 }; 00175 00176 /** 00177 Allocator for space class, a class with a lot of uninitialized 00178 space/members. It uses an instantiate fucntion do initialization 00179 of objects. This is particulary useful if most of the space in 00180 the objects does not need to be intialized. The inifunction passed 00181 can be used to intialize a few fields selectively. Using 00182 ClassAllocator for space objects would unnecessarily initialized 00183 all of the members. 00184 00185 */ 00186 template<class C> class SparseClassAllocator:public ClassAllocator<C> { 00187 public: 00188 00189 /** Allocates objects of the templated type. */ 00190 C* 00191 alloc() 00192 { 00193 void *ptr = ink_freelist_new(this->fl); 00194 00195 if (!_instantiate) { 00196 memcpy(ptr, (void *)&this->proto.typeObject, sizeof(C)); 00197 } else 00198 (*_instantiate) ((C *) &this->proto.typeObject, (C *) ptr); 00199 return (C *) ptr; 00200 } 00201 00202 00203 /** 00204 Create a new class specific SparseClassAllocator. 00205 00206 @param name some identifying name, used for mem tracking purposes. 00207 @param chunk_size number of units to be allocated if free pool is empty. 00208 @param alignment of objects must be a power of 2. 00209 @param instantiate_func 00210 00211 */ 00212 SparseClassAllocator(const char *name, unsigned int chunk_size = 128, 00213 unsigned int alignment = 16, 00214 void (*instantiate_func) (C * proto, C * instance) = NULL) 00215 : ClassAllocator<C>(name, chunk_size, alignment) 00216 { 00217 _instantiate = instantiate_func; // NULL by default 00218 } 00219 00220 private: 00221 void (*_instantiate) (C* proto, C* instance); 00222 }; 00223 00224 #endif // _Allocator_h_