module io.events; import std.socket; import std.outofmemory; private struct evloop { } private struct ev_io { } enum Event { NONE = 0, READ = 1, WRITE = 2, TIMEOUT = 4, ERROR = 128, } private extern (C) void ioev_event_callback(Watcher watcher, int revents) { watcher.callback(revents); } private extern (C) evloop* ioev_ev_default_loop(uint flags); /* is a inline function... */ private extern (C) evloop* ev_loop_new(uint flags); private extern (C) void ev_default_destroy(evloop *loop); private extern (C) void ev_loop_destroy(evloop *loop); private extern (C) void ev_loop(evloop *loop, int flags); private extern (C) void ev_io_start(evloop *loop, ev_io *w); private extern (C) void ev_io_stop(evloop *loop, ev_io *w); private extern (C) ev_io* ioev_io_watcher_new(Watcher watcher); private extern (C) void ioev_io_watcher_free(ev_io *w); private extern (C) void ioev_io_set(ev_io *w, int fd, int events); class Watcher { protected Loop m_cur_loop = null; protected bool m_active = false; protected final Loop loop(Loop l) { if (m_cur_loop is l) return l; if (m_cur_loop !is null) stop(); return m_cur_loop = l; } ~this() { loop = null; } abstract void callback(int revents); abstract protected void do_start(); abstract protected void do_stop(); final public Loop loop() { return m_cur_loop; } final public void start(Loop l) { if (l is null) throw new Exception("Cannot start on null loop"); loop = l; do_start(); m_active = true; } final public void start() { start(m_cur_loop); } final public void stop() { if (!m_active) return; if (m_cur_loop !is null && m_cur_loop.loop !is null) do_stop(); m_active = false; } } class IOWatcher : Watcher { private ev_io *m_w; private Socket m_socket; private Event m_events; private int m_fd = -1; void delegate() read, write, error; this() { m_w = ioev_io_watcher_new(this); if (m_w is null) throw new OutOfMemoryException; } ~this() { ioev_io_watcher_free(m_w); } override final void callback(int revents) { if (revents & Event.READ) read(); if (revents & Event.WRITE) write(); if (revents & Event.ERROR) error(); } private final void set(int fd, int ev) { bool active = m_active; stop(); m_fd = fd; m_events = cast(Event)(ev); ioev_io_set(m_w, m_fd, m_events); if (active) start(); } final Socket socket(Socket s) { m_socket = s; if (m_fd != s.handle) set(s.handle, m_events); return m_socket; } final Event events() { return m_events; } final Event events(int ev) { if (m_events != ev) set(m_fd, ev); return m_events; } final void events(bool waitForRead, bool waitForWrite) { Event ev = Event.NONE; if (waitForRead) ev = ev | Event.READ; if (waitForWrite) ev = ev | Event.WRITE; events(ev); } override final protected void do_start() { ev_io_start(loop.loop, m_w); } override final protected void do_stop() { ev_io_stop(loop.loop, m_w); } } class Loop { protected evloop* loop; private bool default_loop; private static Loop def = null; private this(evloop* loop) { this.loop = loop; default_loop = true; } static synchronized Loop defaultloop() { if (def !is null) return def; evloop* l = ioev_ev_default_loop(0); if (l is null) throw new Exception("ev_default_loop failed"); def = new Loop(l); return def; } this() { default_loop = false; loop = ev_loop_new(0); if (loop is null) throw new Exception("ev_loop_new failed"); } ~this() { if (loop !is null) { if (default_loop) { ev_default_destroy(loop); } else { ev_loop_destroy(loop); } } } final void run() { ev_loop(loop, 0); } }