1 /** 2 Custom versions of std.experimental.allocator functions (unfortunately) 3 */ 4 module automem.allocator; 5 6 import automem.utils: destruct; 7 8 /** 9 10 Destroys and then deallocates (using $(D alloc)) the object pointed to by a 11 pointer, the class object referred to by a $(D class) or $(D interface) 12 reference, or an entire array. It is assumed the respective entities had been 13 allocated with the same allocator. 14 15 */ 16 void dispose(A, T)(auto ref A alloc, T* p) 17 { 18 import std.traits: hasElaborateDestructor; 19 20 static if (hasElaborateDestructor!T) 21 { 22 destruct(*p); 23 } 24 alloc.deallocate((cast(void*) p)[0 .. T.sizeof]); 25 } 26 27 /// Ditto 28 void dispose(A, T)(auto ref A alloc, T p) 29 if (is(T == class) || is(T == interface)) 30 { 31 32 if (!p) return; 33 static if (is(T == interface)) 34 { 35 version(Windows) 36 { 37 import core.sys.windows.unknwn : IUnknown; 38 static assert(!is(T: IUnknown), "COM interfaces can't be destroyed in " 39 ~ __PRETTY_FUNCTION__); 40 } 41 auto ob = cast(Object) p; 42 } 43 else 44 alias ob = p; 45 auto support = (cast(void*) ob)[0 .. typeid(ob).initializer.length]; 46 47 destruct(p); 48 49 alloc.deallocate(support); 50 } 51 52 /// Ditto 53 void dispose(A, T)(auto ref A alloc, T[] array) 54 { 55 import std.traits: hasElaborateDestructor; 56 57 static if (hasElaborateDestructor!(typeof(array[0]))) 58 { 59 foreach (ref e; array) 60 { 61 destruct(e); 62 } 63 } 64 alloc.deallocate(array); 65 } 66 67 @system unittest 68 { 69 70 import std.experimental.allocator: theAllocator, make, makeArray; 71 72 static int x; 73 static interface I 74 { 75 void method(); 76 } 77 static class A : I 78 { 79 int y; 80 override void method() { x = 21; } 81 ~this() { x = 42; } 82 } 83 static class B : A 84 { 85 } 86 auto a = theAllocator.make!A; 87 a.method(); 88 assert(x == 21); 89 theAllocator.dispose(a); 90 assert(x == 42); 91 92 B b = theAllocator.make!B; 93 b.method(); 94 assert(x == 21); 95 theAllocator.dispose(b); 96 assert(x == 42); 97 98 I i = theAllocator.make!B; 99 i.method(); 100 assert(x == 21); 101 theAllocator.dispose(i); 102 assert(x == 42); 103 104 int[] arr = theAllocator.makeArray!int(43); 105 theAllocator.dispose(arr); 106 } 107 108 @system unittest //bugzilla 15721 109 { 110 import std.experimental.allocator: make; 111 import std.experimental.allocator.mallocator : Mallocator; 112 113 interface Foo {} 114 class Bar: Foo {} 115 116 Bar bar; 117 Foo foo; 118 bar = Mallocator.instance.make!Bar; 119 foo = cast(Foo) bar; 120 Mallocator.instance.dispose(foo); 121 }