1 module xbuffer.memory; 2 3 import core.exception : onOutOfMemoryError; 4 import core.memory : pureMalloc, pureCalloc, pureRealloc, pureFree; 5 6 import std.conv : emplace; 7 8 /** 9 * Uses `pureMalloc` to allocate a block of memory of the given 10 * size and throws an `outOfMemoryError` if the memory cannot be 11 * allocated. 12 */ 13 void[] xmalloc(size_t size) pure nothrow @trusted @nogc { 14 void* ptr = pureMalloc(size); 15 if(ptr is null) onOutOfMemoryError(); 16 return ptr[0..size]; 17 } 18 19 /// 20 pure nothrow @trusted @nogc unittest { 21 22 ubyte[] bytes = cast(ubyte[])xmalloc(12); 23 assert(bytes.length == 12); 24 25 int[] ints = cast(int[])xmalloc(12); 26 assert(ints.length == 3); 27 28 } 29 30 /** 31 * Uses `pureCalloc` to allocate a block of memory of the given 32 * size and trows an `outOfMemoryError` if the memory cannot be 33 * allocated. 34 */ 35 void[] xcalloc(size_t nitems, size_t size) pure nothrow @trusted @nogc { 36 void* ptr = pureCalloc(nitems, size); 37 if(ptr is null) onOutOfMemoryError(); 38 return ptr[0..nitems*size]; 39 } 40 41 /// 42 pure nothrow @trusted @nogc unittest { 43 44 ubyte[] bytes = cast(ubyte[])xcalloc(12, 1); 45 assert(bytes.length == 12); 46 47 int[] ints = cast(int[])xcalloc(3, 4); 48 assert(ints.length == 3); 49 50 } 51 52 /** 53 * Uses `pureRealloc` to realloc a block of memory and throws an 54 * `outOfMemoryError` if the memory cannot be allocated. 55 */ 56 void[] xrealloc(void* ptr, size_t size) pure nothrow @trusted @nogc { 57 void* new_ptr = pureRealloc(ptr, size); 58 if(new_ptr is null) onOutOfMemoryError(); 59 return new_ptr[0..size]; 60 } 61 62 /// 63 pure nothrow @trusted @nogc unittest { 64 65 void[] buffer = xmalloc(12); 66 assert(buffer.length == 12); 67 68 // allocate 69 buffer = xrealloc(buffer.ptr, 100); 70 assert(buffer.length == 100); 71 72 // deallocate 73 buffer = xrealloc(buffer, 10); 74 assert(buffer.length == 10); 75 76 } 77 78 /** 79 * Reallocates the given array using a new size. 80 */ 81 void[] xrealloc(T)(ref T[] buffer, size_t size) pure nothrow @trusted @nogc { 82 return (buffer = cast(T[])xrealloc(buffer.ptr, size * T.sizeof)); 83 } 84 85 /// 86 pure nothrow @trusted @nogc unittest { 87 88 ubyte[] bytes = cast(ubyte[])xmalloc(12); 89 xrealloc(bytes, 44); // same as `xrealloc(bytes.ptr, 44)` 90 assert(bytes.length == 44); 91 92 int[] ints = cast(int[])xcalloc(3, 4); 93 assert(ints.length == 3); 94 xrealloc(ints, 4); // same as `xrealloc(ints.ptr, 4 * 4)` 95 assert(ints.length == 4); 96 97 } 98 99 /** 100 * Uses `pureFree` to release allocated memory. 101 */ 102 void xfree(void* ptr) pure nothrow @system @nogc { 103 pureFree(ptr); 104 } 105 106 /// ditto 107 void xfree(T)(ref T[] array) pure nothrow @nogc { 108 xfree(array.ptr); 109 } 110 111 /** 112 * Allocates memory for a class and emplaces it. 113 */ 114 T xalloc(T, E...)(auto ref E args) pure nothrow @system @nogc if(is(T == class)) { 115 return emplace!(T, E)(xmalloc(__traits(classInstanceSize, T)), args); 116 } 117 118 /// 119 pure nothrow @trusted @nogc unittest { 120 121 class Test { 122 123 int a, b, c; 124 125 } 126 127 Test test; 128 assert(test is null); 129 130 test = xalloc!Test(); 131 assert(test !is null); 132 133 } 134 135 /** 136 * Deallocates a class allocated with xalloc and calls its custom 137 * destructor (`__xdtor` pure, nothrow and @nogc method). 138 */ 139 void xfree(T)(T obj) pure nothrow @system @nogc if(is(T == class)) { 140 static if(__traits(hasMember, T, "__xdtor")) obj.__xdtor(); 141 else obj.__dtor(); 142 xfree(cast(void*)obj); 143 }