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 }