1 module upromised.uv.work; 2 import deimos.libuv.uv; 3 import deimos.libuv._d; 4 import std.exception : enforce; 5 import upromised.memory : getSelf, gcretain, gcrelease; 6 import upromised.promise : DelegatePromise, Promisify, Promise; 7 import upromised.uv : uvCheck; 8 9 private { 10 extern(C) void thread_attachThis() nothrow; 11 } 12 13 class Work { 14 private: 15 uv_loop_t* ctx; 16 void delegate() work; 17 DelegatePromise!void result; 18 Promise!void.Value value; 19 20 public: 21 uv_work_t self; 22 23 this(uv_loop_t* ctx) nothrow { 24 this.ctx = ctx; 25 } 26 27 Promise!void run(void delegate() work) nothrow { 28 import upromised.promise : promisifyCall; 29 30 return Promise!void.resolved().then(() { 31 enforce(result is null, "Work already in progress"); 32 33 result = new DelegatePromise!void; 34 scope(failure) result = null; 35 this.work = work; 36 37 auto err = uv_queue_work(ctx, &self, (self) nothrow { 38 thread_attachThis(); 39 40 promisifyCall(self.getSelf!Work().work) 41 .then_((value) nothrow { 42 self.getSelf!Work().value = value; 43 }); 44 }, (selfSelf, status) nothrow { 45 auto self = selfSelf.getSelf!Work; 46 auto result = self.result; 47 self.result = null; 48 result.resolve(self.value); 49 }); 50 err.uvCheck(); 51 52 gcretain(this); 53 result.finall(() { 54 gcrelease(this); 55 }); 56 57 return result; 58 }); 59 } 60 61 Promise!T run(T)(T delegate() cb) nothrow 62 if (is(Promisify!T == Promise!T) && !is(T == void)) 63 { 64 65 T r; 66 return run(() { 67 r = cb(); 68 }).then(() => r); 69 } 70 }