178 lines
3.6 KiB
D
178 lines
3.6 KiB
D
|
|
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);
|
|
}
|
|
}
|