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