1 module dpromise.async;
2 
3 import dpromise.promise;
4 
5 import core.thread : Fiber;
6 import std.concurrency : Generator, yield;
7 import std.traits;
8 
9 Promise!T async(T)(T delegate() dg) nothrow if(!is(Unqual!T : Exception) && !is(Unqual!T : Promise!K, K))
10 in {
11   assert(dg !is null);
12 }body { return promise!T((res, rej) {
13   static if(!is(T == void)) T value;
14 
15   auto gen = new Generator!Awaiter({
16     static if(!is(T == void)) {
17       value = dg();
18     }else {
19       dg();
20     }
21   });
22 
23   void inner() {
24     if(gen.empty) {
25       static if(!is(T == void)) {
26         res(value);
27       }else {
28         res();
29       }
30     }else {
31       gen.front.then(() {
32         gen.popFront;
33         inner();
34       }, (e){
35         rej(e);
36       });
37     }
38   }
39   inner();
40 });}
41 
42 
43 T await(T)(Promise!T promise)
44 in {
45   bool inAsyncFunction() {
46     return (cast(Generator!Awaiter)Fiber.getThis) !is null;
47   }
48   assert(inAsyncFunction);
49 }body {
50 
51   yield(cast(Awaiter)promise);
52 
53   if(promise.isFulfilled) {
54     static if(!is(T == void)) return promise.value;
55   }else if(promise.isRejected) {
56     throw promise.exception;
57   }else {
58     assert(0);
59   }
60 }