1 module concurrency.receiver;
2 
3 import concepts;
4 
5 /// checks that T is a Receiver
6 void checkReceiver(T)() {
7   T t = T.init;
8   import std.traits;
9   alias Params = Parameters!(T.setValue);
10   static if (Params.length == 0)
11     t.setValue();
12   else
13     t.setValue(Params[0].init);
14   (() nothrow => t.setDone())();
15   (() nothrow => t.setError(new Throwable("test")))();
16 }
17 
18 enum isReceiver(T) = is(typeof(checkReceiver!T));
19 
20 auto getStopToken(Receiver)(Receiver r) nothrow @safe if (isReceiver!Receiver) {
21   import concurrency.stoptoken : NeverStopToken;
22   return NeverStopToken();
23 }
24 
25 mixin template ForwardExtensionPoints(alias receiver) {
26   auto getStopToken() nothrow @safe {
27     return receiver.getStopToken();
28   }
29   auto getScheduler() nothrow @safe {
30     return receiver.getScheduler();
31   }
32 }
33 
34 /// A polymorphic receiver of type T
35 interface ReceiverObjectBase(T) {
36   import concurrency.stoptoken : StopToken;
37   import concurrency.scheduler : SchedulerObjectBase;
38   static assert (models!(ReceiverObjectBase!T, isReceiver));
39   static if (is(T == void))
40     void setValue() @safe;
41   else
42     void setValue(T value = T.init) @safe;
43   void setDone() nothrow @safe;
44   void setError(Throwable e) nothrow @safe;
45   StopToken getStopToken() nothrow @safe;
46   SchedulerObjectBase getScheduler() scope nothrow @safe;
47 }
48 
49 struct NullReceiver(T) {
50   void setDone() nothrow @safe @nogc {}
51   void setError(Throwable e) nothrow @safe @nogc {}
52   static if (is(T == void))
53     void setValue() nothrow @safe @nogc {}
54   else
55     void setValue(T t) nothrow @safe @nogc {}
56 }
57 
58 struct ThrowingNullReceiver(T) {
59   void setDone() nothrow @safe @nogc {}
60   void setError(Throwable e) nothrow @safe @nogc {}
61   static if (is(T == void))
62     void setValue() @safe { throw new Exception("ThrowingNullReceiver"); }
63   else
64     void setValue(T t) @safe { throw new Exception("ThrowingNullReceiver"); }
65 }
66 
67 void setValueOrError(Receiver)(auto ref Receiver receiver) @safe {
68   import std.traits;
69   static if (hasFunctionAttributes!(receiver.setValue, "nothrow")) {
70     receiver.setValue();
71   } else {
72     try {
73       receiver.setValue();
74     } catch (Exception e) {
75       receiver.setError(e);
76     }
77   }
78 }
79 
80 void setValueOrError(Receiver, T)(auto ref Receiver receiver, auto ref T value) @safe {
81   import std.traits;
82   static if (hasFunctionAttributes!(receiver.setValue, "nothrow")) {
83     receiver.setValue(value);
84   } else {
85     try {
86       receiver.setValue(value);
87     } catch (Exception e) {
88       receiver.setError(e);
89     }
90   }
91 }