1 /// 2 module libasync.event; 3 4 import core.thread; 5 import libasync.types; 6 import libasync.events; 7 8 /// Takes a raw kernel-emitted file descriptor and registers its events into the event loop for async processing 9 /// NOTE: If it's a socket, it must be made non-blocking before being passed here. 10 /// NOTE: By default dispatched events are READ, WRITE, and ERROR; enabling 'stateful' adds CONNECT and CLOSE 11 class AsyncEvent 12 { 13 nothrow: 14 private: 15 Thread m_owner; 16 EventLoop m_evLoop; 17 fd_t m_evId; 18 bool m_stateful; 19 20 public: 21 /// 22 this(EventLoop evl, fd_t ev_id, bool stateful = false) 23 in { 24 assert(evl !is null && ev_id > 0); 25 } 26 body { 27 m_evLoop = evl; 28 import core.thread : Thread; 29 m_owner = Thread.getThis(); 30 m_evId = ev_id; 31 m_stateful = stateful; 32 } 33 34 /// 35 @property bool hasError() const 36 { 37 return (cast(EventLoop)m_evLoop).status.code != Status.OK; 38 } 39 40 /// Used to diagnose errors when run() or kill() returns false 41 @property StatusInfo status() const { 42 return (cast(EventLoop)m_evLoop).status; 43 } 44 45 /// Human-readable string describing the error 46 @property string error() const { 47 return (cast(EventLoop)m_evLoop).error; 48 } 49 50 /// Registers the signal handler in the event loop 51 bool run(void delegate(EventCode) del) 52 in { 53 debug assert(Thread.getThis() is cast(Thread)m_owner); 54 } 55 body { 56 57 EventHandler handler; 58 handler.del = del; 59 handler.ev = this; 60 return (cast(EventLoop) m_evLoop).run(this, handler); 61 } 62 63 /// Returns the Thread that created this object. 64 synchronized @property Thread owner() const { 65 return cast(Thread) m_owner; 66 } 67 68 /// 69 @property fd_t id() const { 70 return m_evId; 71 } 72 73 /// Removes the event from the event loop, closing the file descriptor if necessary, 74 /// and cleans up the underlying resources. 75 bool kill(bool forced = false) 76 body { 77 scope(exit) m_evId = 0; 78 return m_evLoop.kill(this, forced); 79 } 80 81 package: 82 mixin COSocketMixins; 83 84 @property bool stateful() const { 85 return m_stateful; 86 } 87 88 @property void stateful(bool stateful) { 89 m_stateful = stateful; 90 } 91 92 @property void id(fd_t id) { 93 m_evId = id; 94 } 95 } 96 97 package struct EventHandler { 98 AsyncEvent ev; 99 void delegate(EventCode) del; 100 void opCall(EventCode code){ 101 assert(ev !is null); 102 del(code); 103 assert(ev !is null); 104 return; 105 } 106 } 107 108 /// 109 enum EventCode : char { 110 /// 111 ERROR = 0, 112 /// 113 READ, 114 /// 115 WRITE, 116 /// 117 CONNECT, 118 /// 119 CLOSE 120 }