> 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 <schm...@schmorp.de> wrote:

> On Wed, Jul 07, 2021 at 12:06:37AM +0200, Oleksandr Kozlov <
> aleks.a.koz...@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
>       --==---/ / _ \/ // /\ \/ /      schm...@schmorp.de
>       -=====/_/_//_/\_,_/ /_/\_\
>
_______________________________________________
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/mailman/listinfo/libev

Reply via email to