1 /// Disposable
2 module disposable;
3 
4 /// Indicates that the object(or the inner object in it) can be disposable manually+immediately
5 interface Disposable
6 {
7     /// Disposes unmanaged objects in the object
8     public nothrow void dispose();
9 }
10 
11 /// extended syntax: using!q{ {auto/type} {varname} = {expr}; }
12 pure using(string Q)()
13 {
14     import std.algorithm : map, strip;
15     import std.array : split;
16     import std.ascii : isWhite;
17     import std..string : join;
18     auto ve = Q.split("=").map!(x => x.strip!isWhite);
19     auto tv = ve[0].split!isWhite.map!(x => x.strip!isWhite);
20     return (tv.length <= 1 ? "auto " ~ Q : Q) ~ "; scope(exit) " ~ tv[$ - 1] ~ ".dispose();";
21 }
22 
23 // Using Guard
24 unittest
25 {
26     import std.stdio : writeln;
27 
28     class DisposableInt : Disposable
29     {
30         private int v;
31         private bool disposed;
32 
33         this(int t) { this.v = t; }
34         /// Destructor must call `dispose` with `disposing = false` in its body
35         ~this() { this.dispose(false); }
36 
37         override nothrow void dispose() { this.dispose(true); }
38         nothrow void dispose(bool disposing)
39         {
40             assert(this.disposed != disposing);
41             this.disposed = true;
42         }
43     }
44 
45     mixin(using!q{ auto p = new DisposableInt(2) });
46     static assert(is(typeof(p) == DisposableInt));
47     mixin(using!q{ DisposableInt di = new DisposableInt(2) });
48     mixin(using!q{ d2 = new DisposableInt(2) });
49     static assert(is(typeof(di) == DisposableInt));
50     static assert(is(typeof(d2) == DisposableInt));
51 }
52 // Nested Disposables
53 unittest
54 {
55     class DisposableIntInner : Disposable
56     {
57         private int v;
58         private bool disposed;
59 
60         this(int t) { this.v = t; }
61         ~this() { this.dispose(false); }
62 
63         override nothrow void dispose() { this.dispose(true); }
64         nothrow void dispose(bool disposing)
65         {
66             assert(disposing != this.disposed);
67             this.disposed = true;
68         }
69     }
70     class DisposableIntOuter : Disposable
71     {
72         private int v;
73         private DisposableIntInner inner;
74         private bool disposed;
75 
76         this(int t) { this.v = t; this.inner = new DisposableIntInner(t * 2); }
77         ~this() { this.dispose(false); }
78 
79         override nothrow void dispose() { this.dispose(true); }
80         nothrow void dispose(bool disposing)
81         {
82             assert(this.disposed != disposing);
83             if(disposing) this.inner.dispose();
84             this.disposed = true;
85         }
86     }
87 
88     mixin(using!q{ od = new DisposableIntOuter(4) });
89 }