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 }