This function is mostly exception-safe - you can break out of a ev_run call by calling
longjmp in a callback, throwing a C++ exception and so on. This does not decrement
the ev_depth value, nor will it clear any outstanding EVBREAK_ONE breaks.
A flags value of EVRUN_NOWAIT will look for new events, will handle those events and
any already outstanding ones, but will not wait and block your process in case there
are no events and will return after one iteration of the loop. This is sometimes useful
to poll and handle new events while doing lengthy calculations, to keep the program
responsive.
A flags value of EVRUN_ONCE will look for new events (waiting if necessary) and will
handle those and any already outstanding ones. It will block your process until at
least one new event arrives (which could be an event internal to libev itself, so there
is no guarantee that a user-registered callback will be called), and will return after
one iteration of the loop.
This is useful if you are waiting for some external event in conjunction with
something not expressible using other libev watchers (i.e. "roll your own ev_run").
However, a pair of ev_prepare/ev_check watchers is usually a better approach for this
kind of thing.
Here are the gory details of what ev_run does (this is for your understanding, not a
guarantee that things will work exactly like this in future versions):
- Increment loop depth.
- Reset the ev_break status.
- Before the first iteration, call any pending watchers.
LOOP:
- If EVFLAG_FORKCHECK was used, check for a fork.
- If a fork was detected (by any means), queue and call all fork watchers.
- Queue and call all prepare watchers.
- If ev_break was called, goto FINISH.
- If we have been forked, detach and recreate the kernel state
as to not disturb the other process.
- Update the kernel state with all outstanding changes.
- Update the "event loop time" (ev_now ()).
- Calculate for how long to sleep or block, if at all
(active idle watchers, EVRUN_NOWAIT or not having
any active watchers at all will result in not sleeping).
- Sleep if the I/O and timer collect interval say so.
- Increment loop iteration counter.
- Block the process, waiting for any events.
- Queue all outstanding I/O (fd) events.
- Update the "event loop time" (ev_now ()), and do time jump adjustments.
- Queue all expired timers.
- Queue all expired periodics.
- Queue all idle watchers with priority higher than that of pending events.
- Queue all check watchers.
- Call all queued watchers in reverse order (i.e. check watchers first).
Signals and child watchers are implemented as I/O watchers, and will
be handled here by queueing them when their watcher gets executed.
- If ev_break has been called, or EVRUN_ONCE or EVRUN_NOWAIT
were used, or there are no active watchers, goto FINISH, otherwise
continue with step LOOP.
FINISH:
- Reset the ev_break status iff it was EVBREAK_ONE.
- Decrement the loop depth.
- Return.
Example: Queue some jobs and then loop until no events are outstanding anymore.
libev http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod
第15页 共87页 2017/6/12 上午9:34