问题描述
我正在尝试将 Glib
主循环集成到 libev
事件循环中。实际上,我正在使用他们的 C++ 包装器:glibmm
[1] 和 ev++
[2]。主要思想来自 EV::Glib
Perl 模块 [3]。但是,当我尝试执行一些异步任务(例如,从文件系统读取文本文件)时,我的实现有时会挂起:
#include <ev++.h>
#include <giomm.h>
#include <glibmm.h>
struct context;
int to_ev_events(Glib::IOCondition events) {
int result = EV_NONE;
if ((events & Glib::IOCondition::IO_IN) != Glib::IOCondition{})
result |= EV_READ;
if ((events & Glib::IOCondition::IO_OUT) != Glib::IOCondition{})
result |= EV_WRITE;
return result;
}
Glib::IOCondition to_glib_events(int events) {
Glib::IOCondition result{};
if ((events & EV_READ) != EV_NONE) result |= Glib::IOCondition::IO_IN;
if ((events & EV_WRITE) != EV_NONE) 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();
}
有什么想法吗?
- [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
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)