1 /******************************************************************************* 2 3 Interface for an object allocator. 4 5 Copyright: 6 Copyright (c) 2009-2016 dunnhumby Germany GmbH. 7 All rights reserved. 8 9 License: 10 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 11 Alternatively, this file may be distributed under the terms of the Tango 12 3-Clause BSD License (see LICENSE_BSD.txt for details). 13 14 *******************************************************************************/ 15 16 module ocean.util.container.map.model.IAllocator; 17 18 /******************************************************************************/ 19 20 21 22 abstract class IAllocator 23 { 24 /*************************************************************************** 25 26 Tracks amount of memory used by this allocator. 27 28 ***************************************************************************/ 29 30 private size_t used_memory; 31 32 /*************************************************************************** 33 34 Stores the size of a single allocated element. 35 36 ***************************************************************************/ 37 38 protected size_t bucket_element_size; 39 40 41 /*************************************************************************** 42 43 Constructor. 44 45 Params: 46 bucket_element_sizeof = the amount of memory used by each allocated 47 element. 48 49 ***************************************************************************/ 50 51 public this ( size_t bucket_element_sizeof ) 52 { 53 this.bucket_element_size = bucket_element_sizeof; 54 } 55 56 /*************************************************************************** 57 58 Gets or allocates an object 59 60 Returns: 61 an object that is ready to use. 62 63 ***************************************************************************/ 64 65 public void* get ( ) 66 { 67 this.used_memory += this.bucket_element_size; 68 return this.allocate(); 69 } 70 71 /*************************************************************************** 72 73 Performs the actual allocation of an object 74 75 Returns: 76 an object that is ready to use. 77 78 ***************************************************************************/ 79 80 protected abstract void* allocate (); 81 82 /*************************************************************************** 83 84 Recycles or deletes an object that is no longer used. 85 86 Note: Strictly specking old should be a ref to satisfy D's delete 87 expression which wants the pointer as an lvalue in order to set it to 88 null after deletion. However, would make code more complex and isn't 89 actually necessary in the particular use case of this interface (see 90 BucketSet.remove()/clear()). 91 92 Params: 93 old = old object 94 95 ***************************************************************************/ 96 97 public void recycle ( void* old ) 98 { 99 this.used_memory -= this.bucket_element_size; 100 return this.deallocate(old); 101 } 102 103 /*************************************************************************** 104 105 Performs the actual recycling of an object. See recycle() documentation. 106 107 Params: 108 old = old object 109 110 ***************************************************************************/ 111 112 protected abstract void deallocate ( void* old ); 113 114 /*************************************************************************** 115 116 Return the amount of memory currently used. 117 118 Returns: 119 the size of the memory allocated by this allocator 120 121 ***************************************************************************/ 122 123 public size_t memoryUsed () 124 { 125 return this.used_memory; 126 } 127 128 /*************************************************************************** 129 130 Helper class to temprarily park a certain number of objects. 131 132 ***************************************************************************/ 133 134 static abstract /* scope */ class IParkingStack 135 { 136 import ocean.core.Verify; 137 138 /********************************************************************** 139 140 Maximum number of objects as passed to the constructor. 141 142 **********************************************************************/ 143 144 public size_t max_length ( ) 145 { 146 return this._max_length; 147 } 148 149 private size_t _max_length; 150 151 /********************************************************************** 152 153 Number of elements currently on the stack. This value is always 154 at most max_length. 155 156 **********************************************************************/ 157 158 private size_t n = 0; 159 160 invariant ( ) 161 { 162 assert(this.n <= this._max_length); 163 } 164 165 /********************************************************************** 166 167 Constructor. 168 169 Params: 170 max_length = maximum number of objects that will be stored 171 172 **********************************************************************/ 173 174 protected this ( size_t max_length ) 175 { 176 this._max_length = max_length; 177 } 178 179 /********************************************************************** 180 181 Pushes an object on the stack. 182 183 Params: 184 object = object to push 185 186 Returns: 187 object 188 189 In: 190 Less than max_length objects may be parked. 191 192 **********************************************************************/ 193 194 public void* push ( void* object ) 195 { 196 verify(this.n < this._max_length); 197 198 this.push_(object, this.n++); 199 200 return object; 201 } 202 203 /********************************************************************** 204 205 Pops an object from the stack. 206 207 Returns: 208 object popped from the stack or null if the stack is empty. 209 210 Out: 211 If an element is returned, less than max_length elements must be 212 on the stack, otherwise the stack must be empty. 213 214 **********************************************************************/ 215 216 public void* pop ( ) 217 out (element) 218 { 219 if (element) 220 { 221 assert(this.n < this._max_length); 222 } 223 else 224 { 225 assert(!this.n); 226 } 227 } 228 do 229 { 230 if (this.n) 231 { 232 return this.pop_(--this.n); 233 } 234 else 235 { 236 return null; 237 } 238 } 239 240 /********************************************************************** 241 242 'foreach' iteration, each cycle pops an element from the stack and 243 iterates over it. 244 245 **********************************************************************/ 246 247 public int opApply ( scope int delegate ( ref void* object ) dg ) 248 { 249 int r = 0; 250 251 for (void* object = this.pop(); object && !r; object = this.pop()) 252 { 253 r = dg(object); 254 } 255 256 return r; 257 } 258 259 /********************************************************************** 260 261 Pushes an object on the stack. 262 263 Params: 264 object = object to push 265 n = number of parked objects before object is pushed 266 (guaranteed to be less than max_length) 267 268 **********************************************************************/ 269 270 abstract protected void push_ ( void* object, size_t n ); 271 272 /********************************************************************** 273 274 Pops an object from the stack. This method is never called if the 275 stack is empty. 276 277 Params: 278 n = number of parked objects after object is popped (guaranteed 279 to be less than max_length) 280 281 Returns: 282 object popped from the stack or null if the stack is empty. 283 284 **********************************************************************/ 285 286 abstract protected void* pop_ ( size_t n ); 287 } 288 289 /*************************************************************************** 290 291 Calls dg with an IParkingStack instance that is set up to keep n 292 elements. 293 294 Params: 295 n = number of elements to park 296 dg = delegate to call with the IParkingStack instance 297 298 ***************************************************************************/ 299 300 void parkElements ( size_t n, scope void delegate ( IParkingStack park ) dg ); 301 }