1 module concurrency.operations.finally_; 2 3 import concurrency; 4 import concurrency.receiver; 5 import concurrency.sender; 6 import concurrency.stoptoken; 7 import concepts; 8 import std.traits; 9 10 deprecated("don't use it, the semantics aren't correct") 11 auto finally_(Sender, Result)(Sender sender, Result result) { 12 import std.traits : isCallable; 13 return FinallySender!(Sender, Result)(sender, result); 14 } 15 16 private struct FinallyReceiver(Value, Result, Receiver) { 17 Receiver receiver; 18 Result result; 19 private auto getResult() { 20 static if (isCallable!Result) 21 return result(); 22 else return result; 23 } 24 static if (is(Value == void)) 25 void setValue() @safe { 26 receiver.setValue(getResult()); 27 } 28 else 29 void setValue(Value value) @safe { 30 receiver.setValue(getResult()); 31 } 32 void setDone() @safe nothrow { 33 receiver.setDone(); 34 } 35 void setError(Throwable e) @safe nothrow { 36 receiver.setValue(getResult()); 37 } 38 mixin ForwardExtensionPoints!receiver; 39 } 40 41 struct FinallySender(Sender, Result) if (models!(Sender, isSender)) { 42 static assert (models!(typeof(this), isSender)); 43 static if (isCallable!Result) 44 alias Value = typeof(result()); 45 else 46 alias Value = Result; 47 Sender sender; 48 Result result; 49 auto connect(Receiver)(return Receiver receiver) @safe scope return { 50 // ensure NRVO 51 auto op = sender.connect(FinallyReceiver!(Sender.Value, Result, Receiver)(receiver, result)); 52 return op; 53 } 54 } 55