3

Let's say I have 2 sockets I am watching for events and I really want socket 1 to be preferred (even at the cost of starving socket 2). How would I do that with libev (I asked the same question about libuv here but it looks like libuv cannot do that) ?

As an example when working with libevent one can use :

int event_priority_set(struct event *event, int priority);

When multiple events of multiple priorities become active, the low-priority events are not run. Instead, Libevent runs the high priority events, then checks for events again. Only when no high-priority events are active are the low-priority events run.

Community
  • 1
  • 1
Alex Garcia
  • 773
  • 7
  • 21

2 Answers2

1

Check libev function ev_set_priority():

ev_set_priority (ev_TYPE *watcher, int priority)

Set and query the priority of the watcher. The priority is a small integer between EV_MAXPRI (default: 2) and EV_MINPRI (default: -2). Pending watchers with higher priority will be invoked before watchers with lower priority, but priority will not keep watchers from being executed (except for ev_idle watchers).

http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#GENERIC_WATCHER_FUNCTIONS

Ales Teska
  • 1,198
  • 1
  • 17
  • 38
1

ev_set_priority, despite the name, does not in itself do what you want, it only changes the relative order of callback invocation, with one exception: ev_idle watchers.

For ev_idle watchers, the lower priority watchers are indeed not invoked when other events, or higher priority idle watchers, are pending. For example, ev_idle watchers with priority 0 will be handled when there are no other pending watchers with priority 0 (the default), i.e. it will only be invoked when no other events with priority 0 are pending. Libev will check for more events before making this decision, so for as long as there are events with priority 0 or higher, it will not invoke idle watchers with priority 0 or lower.

One way to solve your problem is to only start an ev_idle watcher in the io callback for your non-preferred socket with a priority equal to the priority on the io watcher, causing it to not be handled until all other events are handled.

A slight variation would be to mark your low prioprity io watchers in some sort of set and start a single ev_idle watcher, which then goes through all sockets in your set.

Another, completely different way would be to look into embeddable event loops and move all lower priority io watchers into an embedded loop. In your ev_embed watcher callback you can then start an idle watcher to later call ev_embed_sweep. This has the advantage of needing fewer idle watchers and moving all the processing for the low-priority sockets into their own event loop, so they don't cause extra latency issues for your high priority io watcher.

Alex Garcia
  • 773
  • 7
  • 21
Remember Monica
  • 3,897
  • 1
  • 24
  • 31
  • Thanks for the detailed answer! I'm not working on that now but when I get back to it I'll definitely give it more thought – Alex Garcia Jun 15 '18 at 07:14