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 41 if (!p) { 42 return; 43 } 44 45 destroy(p); 46 CPPAllocator.instance.dispose(cast(void*) p); //Workaround for prevent error "Runtime type information is not supported for extern(C++) classes" 47 } 48 49 void CPPDelete(T) (auto ref T[] array) { 50 import std.experimental.allocator : dispose; 51 CPPAllocator.instance.dispose(array); 52 } 53 54 void CPPDeleteMultidimensionalArray(T)(auto ref T[] array) { 55 import std.experimental.allocator : disposeMultidimensionalArray; 56 CPPAllocator.instance.disposeMultidimensionalArray(array); 57 } 58 59 struct CPPAllocator { 60 import std.experimental.allocator.common : platformAlignment; 61 import core.stdcpp.xutility : __cpp_aligned_new; 62 63 /** 64 * Returns the global instance of this allocator type. 65 * CppNew is thread-safe, all methods are shared. 66 */ 67 static shared CPPAllocator instance; 68 69 /** 70 * The alignment is a static constant equal to `platformAlignment`, which 71 * ensures proper alignment for any D data type. 72 */ 73 enum uint alignment = platformAlignment; 74 75 /** 76 * Allocates the size expressed in bytes. 77 * 78 * Params: 79 * bytes = Number of bytes to allocate. 80 * 81 * Returns: 82 * An array with allocated memory or null if out of memory. Returns null if called with size 0. 83 */ 84 @trusted @nogc nothrow void[] allocate(size_t bytes) shared { 85 import core.stdcpp.new_ : __cpp_new_nothrow; 86 87 if (bytes == 0) { 88 return null; 89 } 90 91 auto p = __cpp_new_nothrow(bytes); 92 return p ? p[0 .. bytes] : null; 93 } 94 95 /** 96 * Allocates the size expressed in bytes aligned by alignment. 97 * 98 * Params: 99 * bytes = Number of bytes to allocate. 100 * alignment = the minimal alignment of the allocated memory. 101 * 102 * Returns: 103 * An array with aligned allocated memory or null if out of memory. Returns null if called with size 0. 104 */ 105 static if (__cpp_aligned_new) { 106 @trusted @nogc nothrow void[] alignedAllocate(size_t bytes, uint alignment) shared { 107 import core.stdcpp.new_ : __cpp_new_aligned_nothrow; 108 109 if (bytes == 0) { 110 return null; 111 } 112 113 auto p = __cpp_new_aligned_nothrow(bytes, alignment); 114 return p ? p[0 .. bytes] : null; 115 } 116 } 117 118 119 /** 120 * Deallocate the specified memory block 121 * 122 * Params: 123 * b = The memory block to be deallocated. 124 * 125 * Returns: 126 * false if the array is null, otherwise true. 127 */ 128 @system @nogc nothrow bool deallocate(void[] b) shared { 129 import core.stdcpp.new_ : __cpp_delete_nothrow; 130 131 if (b is null) { 132 return true; 133 } 134 135 __cpp_delete_nothrow(b.ptr); 136 return true; 137 } 138 }