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