I am trying to integrate the Glib main loop into the libev event loop. Actually, I am using their C++ wrappers: glibmm [1] and ev++ [2]. The main idea was taken from the EV::Glib Perl module [3]. However, my implementation sometimes hangs when I try to perform some async task (e.g., reading a text file from the filesystem):
#include <ev++.h> #include <giomm.h> #include <glibmm.h> struct context; int to_ev_events(Glib::IOCondition events) { int result = EV_NONE; if (events == (events & Glib::IOCondition::IO_IN)) result |= EV_READ; if (events == (events & Glib::IOCondition::IO_OUT)) result |= EV_WRITE; return result; } Glib::IOCondition to_glib_events(int events) { Glib::IOCondition result{}; if (events == (events & EV_READ)) result |= Glib::IOCondition::IO_IN; if (events == (events & EV_WRITE)) result |= Glib::IOCondition::IO_OUT; return result; } struct prepare_watcher { prepare_watcher(context &c) : ctx{c} { watcher.priority = EV_MINPRI; watcher.set(this); watcher.start(); } void operator()(ev::prepare &watcher, int revents); ev::prepare watcher; context &ctx; }; struct check_watcher { check_watcher(context &c) : ctx{c} { watcher.priority = EV_MAXPRI; watcher.set(this); watcher.start(); } void operator()(ev::check &watcher, int revents); ev::check watcher; context &ctx; }; struct timer_watcher { timer_watcher() { watcher.priority = EV_MINPRI; } ev::timer watcher; }; struct io_watcher { io_watcher(int fd, int events) { watcher.priority = EV_MINPRI; watcher.start(fd, events); } ev::io watcher; }; struct context { Glib::RefPtr<Glib::MainContext> context = Glib::MainContext::get_default(); ev::default_loop loop; std::vector<Glib::PollFD> poll_fds; int priority{}; prepare_watcher prepare{*this}; check_watcher check{*this}; timer_watcher timer; std::map<int, io_watcher> ios; }; void prepare_watcher::operator()(ev::prepare &watcher, int revents) { ctx.context->dispatch(); ctx.context->prepare(ctx.priority); ctx.poll_fds.clear(); int timeout = 0; ctx.context->query(ctx.priority, timeout, ctx.poll_fds); for (Glib::PollFD &poll_fd : ctx.poll_fds) { int fd = poll_fd.get_fd(); ctx.ios.try_emplace(fd, fd, to_ev_events(poll_fd.get_events())); } if (timeout >= 0) ctx.timer.watcher.start(timeout * 1e-3); } void check_watcher::operator()(ev::check &watcher, int revents) { for (Glib::PollFD &poll_fd : ctx.poll_fds) { int fd = poll_fd.get_fd(); io_watcher &io = ctx.ios.at(fd); if (io.watcher.is_pending()) poll_fd.set_revents( to_glib_events(ev_clear_pending(ctx.loop.raw_loop, &io.watcher))); ctx.ios.erase(fd); } if (ctx.timer.watcher.is_active() || ctx.timer.watcher.is_pending()) ctx.timer.watcher.stop(); ctx.context->check(ctx.priority, ctx.poll_fds); } int main() { Gio::init(); context ctx; Glib::RefPtr<Gio::File> file = Gio::File::create_for_path("file.txt"); file->read_async([&](Glib::RefPtr<Gio::AsyncResult> result) { file->read_finish(result); ctx.loop.break_loop(ev::ALL); }); ctx.loop.run(); } Any ideas? * [1] https://github.com/GNOME/glibmm * [2] http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#C_API-2 * [3] https://github.com/gitpan/EV-Glib/blob/master/Glib.xs
_______________________________________________ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/mailman/listinfo/libev