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 }