Integrate the Glib main loop into the libev event loop (C++)
Oleksandr Kozlov
aleks.a.kozlov at gmail.com
Wed Jul 7 08:59:01 CEST 2021
> this is likely going to be slow
Yeah, but performance is not a concern for my use case.
> you could simply push them onto a vector and clear
it out in check.
I've tried to replace std::map with std::vector, but this didn't help.
Actually, I used std::list instead of std::vector, because ev::io has
a private copy constructor, but we might need to resize a vector
and move I/O watchers. I ended up with the following code:
for (auto &io : ctx.ios) {
if (io.watcher.is_pending()) {
auto poll_fd = std::find_if(
ctx.poll_fds.begin(), ctx.poll_fds.end(),
[&](Glib::PollFD &poll) { return poll.get_fd() == io.watcher.fd; });
if (poll_fd != ctx.poll_fds.end()) {
poll_fd->set_revents(
to_glib_events(ev_clear_pending(ctx.loop.raw_loop, &io.watcher)));
}
}
}
ctx.ios.clear();
By the way, it turned out that C-language implementation from EV::Glib
behaves in the same way: also hangs.
It worth to mention, that I've tried to create ev::idle to prevent the
event loop
from sleeping. This solves the problem with hanging, but the busy loop loads
CPU for 100%.
> You could also try forcing libev to use select or poll as backend
I will try to use select or poll as a backend. Thanks for the idea.
On Wed, Jul 7, 2021 at 3:21 AM Marc Lehmann <schmorp at schmorp.de> wrote:
> On Wed, Jul 07, 2021 at 12:06:37AM +0200, Oleksandr Kozlov <
> aleks.a.kozlov at gmail.com> wrote:
> > from the EV::Glib Perl module [3].
>
> Note that this is likely going to be slow, as glib does not have the
> necessary hooks to efficiently be embedded into another event loop.
>
> > 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()));
>
> This looks as if you cache io watchers by fd, and could be the reason for
> the problem - Glib doesn't tell you when the fd changes, so the fd is not
> a unique enough primary key for your map (which really should be an array,
> too).
>
> What EV::Glib is doing is create I/O watchers in a prepare call and stop
> them in the check call - you could simply push them onto a vector and clear
> it out in check.
>
> You could also try forcing libev to use select or poll as backend, which,
> if Glib uses a lot of watchers, is likely more efficient, and this is a
> quick way of checking whether this is your real problem - note that using
> these backends for these side effects is not really supported by libev,
> so you should definitely fix the c++ side, possibly followed by using
> select/poll for efficiency.
>
> --
> The choice of a Deliantra, the free code+content
> MORPG
> -----==- _GNU_ http://www.deliantra.net
> ----==-- _ generation
> ---==---(_)__ __ ____ __ Marc Lehmann
> --==---/ / _ \/ // /\ \/ / schmorp at schmorp.de
> -=====/_/_//_/\_,_/ /_/\_\
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.schmorp.de/pipermail/libev/attachments/20210707/ad5934df/attachment.htm>
More information about the libev
mailing list