1 /******************************************************************************* 2 3 Interface and GC / malloc implementations of a memory manager which can 4 create and destroy chunks of memory. 5 6 Copyright: 7 Copyright (c) 2009-2016 dunnhumby Germany GmbH. 8 All rights reserved. 9 10 License: 11 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 12 Alternatively, this file may be distributed under the terms of the Tango 13 3-Clause BSD License (see LICENSE_BSD.txt for details). 14 15 *******************************************************************************/ 16 17 module ocean.util.container.mem.MemManager; 18 19 20 21 import ocean.core.Enforce; 22 23 import ocean.core.ExceptionDefinitions : onOutOfMemoryError; 24 25 import core.stdc.stdlib : malloc, free; 26 27 import core.memory; 28 29 import ocean.meta.types.Qualifiers; 30 31 /******************************************************************************* 32 33 C Malloc memory manager instance, 34 not scanned by the gc for pointers/references 35 36 *******************************************************************************/ 37 38 __gshared IMemManager noScanMallocMemManager; 39 40 41 /******************************************************************************* 42 43 C Malloc memory manager instance, scanned by the gc for pointers/references 44 45 *******************************************************************************/ 46 47 __gshared IMemManager mallocMemManager; 48 49 50 /******************************************************************************* 51 52 GC memory manager instance, 53 not scanned by the gc for pointers/references 54 55 *******************************************************************************/ 56 57 __gshared IMemManager noScanGcMemManager; 58 59 60 /******************************************************************************* 61 62 GC memory manager instance, scanned by the gc for pointers/references 63 64 *******************************************************************************/ 65 66 __gshared IMemManager gcMemManager; 67 68 shared static this ( ) 69 { 70 noScanMallocMemManager = new MallocMemManager!(false); 71 noScanGcMemManager = new GCMemManager!(false); 72 mallocMemManager = new MallocMemManager!(true); 73 gcMemManager = new GCMemManager!(true); 74 } 75 76 /******************************************************************************* 77 78 Memory manager interface. 79 80 *******************************************************************************/ 81 82 public interface IMemManager 83 { 84 /*************************************************************************** 85 86 Allocates a buffer of the specified dimension. 87 88 Params: 89 dimension = bytes to allocate 90 91 Returns: 92 new buffer 93 94 ***************************************************************************/ 95 96 public ubyte[] create ( size_t dimension ); 97 98 99 /*************************************************************************** 100 101 Explicit deallocation 102 103 Note that it is up to the user of classes which implement this interface 104 to ensure that the buffer passed was in fact allocated by the same 105 instance. 106 107 Params: 108 buffer = buffer to deallocate 109 110 ***************************************************************************/ 111 112 public void destroy ( ubyte[] buffer ); 113 114 /*************************************************************************** 115 116 Destructor compatible deallocation 117 118 Note that it is up to the user of classes which implement this interface 119 to ensure that the buffer passed was in fact allocated by the same 120 instance. 121 122 The destructor is always called when an object is collected or when it 123 is explicitly deleted. This method is intended to be called from the 124 destructor. 125 126 Params: 127 buffer = buffer to cleanup 128 129 ***************************************************************************/ 130 131 public void dtor ( ubyte[] buffer ); 132 } 133 134 135 136 /******************************************************************************* 137 138 Memory manager implementation using the D garbage collector. 139 140 Template Parameters: 141 gc_aware = whether the gc should scan the allocated memory for 142 pointers or references 143 144 *******************************************************************************/ 145 146 private class GCMemManager ( bool gc_aware ) : IMemManager 147 { 148 /*************************************************************************** 149 150 Allocates a buffer of the specified dimension via the GC. 151 152 Params: 153 dimension = bytes to allocate 154 155 Returns: 156 new buffer 157 158 ***************************************************************************/ 159 160 public override ubyte[] create ( size_t dimension ) 161 { 162 static if ( gc_aware ) 163 { 164 return cast(ubyte[]) new void[dimension]; 165 } 166 else 167 { 168 return new ubyte[dimension]; 169 } 170 } 171 172 173 /*************************************************************************** 174 175 Explicit deallocation 176 177 Note that it is up to the user of classes which implement this interface 178 to ensure that the buffer passed was in fact allocated by the same 179 instance. 180 181 Params: 182 buffer = buffer to deallocate 183 184 ***************************************************************************/ 185 186 public override void destroy ( ubyte[] buffer ) 187 { 188 import core.memory; 189 GC.free(buffer.ptr); 190 } 191 192 /*************************************************************************** 193 194 Destructor compatible deallocation 195 196 Note that it is up to the user of classes which implement this interface 197 to ensure that the buffer passed was in fact allocated by the same 198 instance. 199 200 The destructor is always called when an object is collected or when it 201 is explicitly deleted. This method is intended to be called from the 202 destructor. 203 204 Params: 205 buffer = buffer to cleanup 206 207 ***************************************************************************/ 208 209 public override void dtor ( ubyte[] buffer ) 210 { 211 } 212 } 213 214 215 216 /******************************************************************************* 217 218 Memory manager implementation using malloc and free. 219 220 Template Parameters: 221 gc_aware = whether the gc should scan the allocated memory for 222 pointers or references 223 224 *******************************************************************************/ 225 226 private class MallocMemManager ( bool gc_aware ) : IMemManager 227 { 228 /*************************************************************************** 229 230 Allocates a buffer of the specified dimension using malloc. 231 232 Params: 233 dimension = bytes to allocate 234 235 Returns: 236 new buffer 237 238 ***************************************************************************/ 239 240 public override ubyte[] create ( size_t dimension ) 241 { 242 auto ptr = cast(ubyte*)malloc(dimension); 243 if (ptr is null) 244 { 245 onOutOfMemoryError(); 246 } 247 248 static if ( gc_aware ) 249 { 250 GC.addRange(ptr, dimension); 251 } 252 253 return ptr[0..dimension]; 254 } 255 256 257 /*************************************************************************** 258 259 Explicit deallocation 260 261 Note that it is up to the user of classes which implement this interface 262 to ensure that the buffer passed was in fact allocated by the same 263 instance. 264 265 Params: 266 buffer = buffer to deallocate 267 268 ***************************************************************************/ 269 270 public override void destroy ( ubyte[] buffer ) 271 { 272 if ( buffer.ptr !is null ) 273 { 274 static if ( gc_aware ) 275 { 276 GC.removeRange(buffer.ptr); 277 } 278 279 free(buffer.ptr); 280 } 281 } 282 283 /*************************************************************************** 284 285 Destructor compatible deallocation 286 287 Note that it is up to the user of classes which implement this interface 288 to ensure that the buffer passed was in fact allocated by the same 289 instance. 290 291 The destructor is always called when an object is collected or when it 292 is explicitly deleted. This method is intended to be called from the 293 destructor. 294 295 Params: 296 buffer = buffer to cleanup 297 298 ***************************************************************************/ 299 300 public override void dtor ( ubyte[] buffer ) 301 { 302 if ( buffer.ptr !is null ) 303 { 304 static if ( gc_aware ) 305 { 306 GC.removeRange(buffer.ptr); 307 } 308 309 free(buffer.ptr); 310 } 311 } 312 }