1 /* 2 Copyright (c) 2016-2021 Eugene Wissner 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license (the "Software") to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 */ 28 29 /** 30 * Allocator based on malloc/realloc/free 31 * 32 * Copyright: Eugene Wissner 2016-2021. 33 * License: $(LINK2 boost.org/LICENSE_1_0.txt, Boost License 1.0). 34 * Authors: Eugene Wissner 35 */ 36 module dlib.memory.mallocator; 37 38 import dlib.memory.allocator; 39 import core.exception; 40 import core.stdc.stdlib; 41 import std.algorithm.comparison; 42 43 /** 44 * Wrapper for malloc/realloc/free from the C standard library. 45 */ 46 class Mallocator : Allocator 47 { 48 /** 49 * Allocates $(D_PARAM size) bytes of memory. 50 * 51 * Params: 52 * size = Amount of memory to allocate. 53 * 54 * Returns: The pointer to the new allocated memory. 55 */ 56 void[] allocate(size_t size) 57 { 58 if (!size) 59 { 60 return null; 61 } 62 auto p = malloc(size); 63 64 if (!p) 65 { 66 onOutOfMemoryError(); 67 } 68 return p[0..size]; 69 } 70 71 /// 72 unittest 73 { 74 auto p = Mallocator.instance.allocate(20); 75 76 assert(p.length == 20); 77 78 Mallocator.instance.deallocate(p); 79 } 80 81 /** 82 * Deallocates a memory block. 83 * 84 * Params: 85 * p = A pointer to the memory block to be freed. 86 * 87 * Returns: Whether the deallocation was successful. 88 */ 89 bool deallocate(void[] p) 90 { 91 if (p !is null) 92 { 93 free(p.ptr); 94 } 95 return true; 96 } 97 98 /// 99 unittest 100 { 101 void[] p; 102 assert(Mallocator.instance.deallocate(p)); 103 104 p = Mallocator.instance.allocate(10); 105 assert(Mallocator.instance.deallocate(p)); 106 } 107 108 /** 109 * Increases or decreases the size of a memory block. 110 * 111 * Params: 112 * p = A pointer to the memory block. 113 * size = Size of the reallocated block. 114 * 115 * Returns: Whether the reallocation was successful. 116 */ 117 bool reallocate(ref void[] p, size_t size) 118 { 119 if (!size) 120 { 121 deallocate(p); 122 p = null; 123 return true; 124 } 125 else if (p is null) 126 { 127 p = allocate(size); 128 return true; 129 } 130 auto r = realloc(p.ptr, size); 131 132 if (!r) 133 { 134 onOutOfMemoryError(); 135 } 136 p = r[0..size]; 137 138 return true; 139 } 140 141 /// 142 unittest 143 { 144 void[] p; 145 146 Mallocator.instance.reallocate(p, 20); 147 assert(p.length == 20); 148 149 Mallocator.instance.reallocate(p, 30); 150 assert(p.length == 30); 151 152 Mallocator.instance.reallocate(p, 10); 153 assert(p.length == 10); 154 155 Mallocator.instance.reallocate(p, 0); 156 assert(p is null); 157 } 158 159 /** 160 * Returns: The alignment offered. 161 */ 162 @property immutable(uint) alignment() const 163 { 164 return cast(uint) max(double.alignof, real.alignof); 165 } 166 167 /** 168 * Static allocator instance and initializer. 169 * 170 * Returns: The global $(D_PSYMBOL Allocator) instance. 171 */ 172 static @property Mallocator instance() @nogc nothrow 173 { 174 if (instance_ is null) 175 { 176 immutable size = __traits(classInstanceSize, Mallocator); 177 void* p = malloc(size); 178 179 if (p is null) 180 { 181 onOutOfMemoryError(); 182 } 183 p[0..size] = typeid(Mallocator).initializer[]; 184 instance_ = cast(Mallocator) p[0..size].ptr; 185 } 186 return instance_; 187 } 188 189 /// 190 @nogc nothrow unittest 191 { 192 assert(instance is instance); 193 } 194 195 private static __gshared Mallocator instance_; 196 }