1 module cppnew; 2 3 auto CPPNew(T, A...) (auto ref A args) { 4 import std.experimental.allocator : make; 5 return CPPAllocator.instance.make!T(args); 6 } 7 8 T[] CPPNewArray(T) (size_t length) { 9 import std.experimental.allocator : makeArray; 10 return CPPAllocator.instance.makeArray!T(length); 11 } 12 13 T[] CPPNewArray(T) (size_t length, T init) { 14 import std.experimental.allocator : makeArray; 15 return CPPAllocator.instance.makeArray!T(length, init); 16 } 17 18 Unqual!(ElementEncodingType!R)[] CPPNewArray(R)(R range) if (isInputRange!R && !isInfinite!R) { 19 import std.experimental.allocator : makeArray; 20 return CPPAllocator.instance.makeArray!T(range); 21 } 22 23 T[] CPPNewArray(T, R)(R range) if (isInputRange!R && !isInfinite!R) { 24 import std.experimental.allocator : makeArray; 25 return CPPAllocator.instance.makeArray!T(range); 26 } 27 28 auto CPPNewMultidimensionalArray(T, size_t N)(size_t[N] lengths...) { 29 import std.experimental.allocator : makeMultidimensionalArray; 30 return CPPAllocator.instance.makeMultidimensionalArray!T(lengths); 31 } 32 33 void CPPDelete(T) (auto ref T* p) { 34 import std.experimental.allocator : dispose; 35 CPPAllocator.instance.dispose(p); 36 } 37 38 void CPPDelete(T) (auto ref T p) if (is(T == class) || is(T == interface)) { 39 import std.experimental.allocator : dispose; 40 CPPAllocator.instance.dispose(p); 41 } 42 43 void CPPDelete(T) (auto ref T[] array) { 44 import std.experimental.allocator : dispose; 45 CPPAllocator.instance.dispose(array); 46 } 47 48 void CPPDeleteMultidimensionalArray(T)(auto ref T[] array) { 49 import std.experimental.allocator : disposeMultidimensionalArray; 50 CPPAllocator.instance.disposeMultidimensionalArray(array); 51 } 52 53 struct CPPAllocator { 54 import std.experimental.allocator.common : platformAlignment; 55 import core.stdcpp.xutility : __cpp_aligned_new; 56 57 /** 58 * Returns the global instance of this allocator type. 59 * CppNew is thread-safe, all methods are shared. 60 */ 61 static shared CPPAllocator instance; 62 63 /** 64 * The alignment is a static constant equal to `platformAlignment`, which 65 * ensures proper alignment for any D data type. 66 */ 67 enum uint alignment = platformAlignment; 68 69 /** 70 * Allocates the size expressed in bytes. 71 * 72 * Params: 73 * bytes = Number of bytes to allocate. 74 * 75 * Returns: 76 * An array with allocated memory or null if out of memory. Returns null if called with size 0. 77 */ 78 @trusted @nogc nothrow void[] allocate(size_t bytes) shared { 79 import core.stdcpp.new_ : __cpp_new_nothrow; 80 81 if (bytes == 0) { 82 return null; 83 } 84 85 auto p = __cpp_new_nothrow(bytes); 86 return p ? p[0 .. bytes] : null; 87 } 88 89 /** 90 * Allocates the size expressed in bytes aligned by alignment. 91 * 92 * Params: 93 * bytes = Number of bytes to allocate. 94 * alignment = the minimal alignment of the allocated memory. 95 * 96 * Returns: 97 * An array with aligned allocated memory or null if out of memory. Returns null if called with size 0. 98 */ 99 static if (__cpp_aligned_new) { 100 @trusted @nogc nothrow void[] alignedAllocate(size_t bytes, uint alignment) shared { 101 import core.stdcpp.new_ : __cpp_new_aligned_nothrow; 102 103 if (bytes == 0) { 104 return null; 105 } 106 107 auto p = __cpp_new_aligned_nothrow(bytes, alignment); 108 return p ? p[0 .. bytes] : null; 109 } 110 } 111 112 113 /** 114 * Deallocate the specified memory block 115 * 116 * Params: 117 * b = The memory block to be deallocated. 118 * 119 * Returns: 120 * false if the array is null, otherwise true. 121 */ 122 @system @nogc nothrow bool deallocate(void[] b) shared { 123 import core.stdcpp.new_ : __cpp_delete_nothrow; 124 125 if (b is null) { 126 return true; 127 } 128 129 __cpp_delete_nothrow(b.ptr); 130 return true; 131 } 132 }