Original address: http://www.yeolar.com/note/2012/12/16/libev/
------------
usage of the Libev library
Yeolar 2012-12-16 21:12
Libev is a high-performance event loop library that performs better than the Libevent library. Nodejs is using it as the underlying library. Libev's official documentation is here, the document is relatively long. This article combines the examples to make a brief summary of its usage.
Catalogue Examples
Let's start with the official example:
A single header file was required #include <ev.h> #include <stdio.h>//for puts//every watcher type have
Its own typedef ' d-struct//with the name Ev_type Ev_io stdin_watcher;
Ev_timer Timeout_watcher; All watcher callbacks has a similar signature//This callback are called when data are readable on stdin static void St
DIN_CB (ev_p_ ev_io *w, int revents) {puts ("stdin ready");
For one-shot events, one must manually stop of the Watcher//with its corresponding stop function.
Ev_io_stop (Ev_a_ W);
This causes all nested Ev_run's to stop iterating Ev_break (Ev_a_ evbreak_all); }//Another callback, this time for a time-out static void Timeout_cb (Ev_p_ ev_timer *w, int revents) {puts ("Timeou
T ");
This causes the innermost ev_run to stop iterating Ev_break (Ev_a_ evbreak_one);
} int main (void) {//Use the default event loop unless special needs struct ev_loop *loop = Ev_default; Initialise an IO watcher, then startIT//This one'll watch for stdin to become readable ev_io_init (&stdin_watcher, STDIN_CB,/*stdin_fileno*/0, E
V_read);
Ev_io_start (Loop, &stdin_watcher); Initialise a timer watcher, then start it//simple non-repeating 5.5 second timeout ev_timer_init (&timeout_wa
Tcher, TIMEOUT_CB, 5.5, 0.);
Ev_timer_start (Loop, &timeout_watcher);
Now wait for events to arrive Ev_run (loop, 0);
Break is called, so exit return 0;
}
This example first creates an event loop and then registers two events: Read the standard input events and timeout events. Ends the event loop after terminal input or timeout. Event Loops
The core of using Libev is the event loop, you can create loops with ev_default_loop or ev_loop_new functions, or use Ev_default macros directly, except that the event loops created by Ev_default_loop are not thread-safe, and EV_ The event loop created by Loop_new cannot capture the signal and the observer for the child process. In most cases, it can be used as follows:
if (!ev_default_loop (0))
fatal ("Could not initialise Libev, bad $LIBEV _flags in environment?");
Or explicitly select a backend:
struct Ev_loop *epoller = ev_loop_new (Evbackend_epoll | EVFLAG_NOENV);
if (!epoller)
fatal ("No epoll found here, maybe it hides under your chair");
If you need to dynamically allocate loops, we recommend using Ev_loop_new and Ev_loop_destroy.
After the child process is created and you want to use the event loop, you need to call ev_default_fork or ev_loop_fork in the child process to reinitialize the back-end kernel state, which is used for Ev_default_loop and ev_loop_new, respectively.
Ev_run start the event loop. Its second argument is 0 o'clock, which continues to run and processes the loop until there are no active event observers or calls to Ev_break. The other two values are evrun_nowait and evrun_once.
The ev_break jumps out of the event loop (after all events that have occurred have finished processing). The second parameter is Evbreak_one or Evbreak_all to specify the ev_run that jumps out of the inner layer or all nested ev_run.
Ev_suspend and Ev_resume are used to pause and restart event loops, such as when a program hangs. Observation Device
Next, you create the Observer, which mainly includes types, trigger conditions, and callback functions. Registering it on the event loop triggers the observer to invoke its callback function when the registration condition is met.
The above example already includes the IO Observer and the timer Observer, as well as the periodic observer, the Signal Observer, the file Status Viewer, and so on.
Initialize and set observers use Ev_init and Ev_type_set, or you can use Ev_type_init directly.
Start the observer using Ev_type_start on a particular event loop. Ev_type_stop stops the viewer and frees up memory.
The Libev is divided into 4 states: Initialize, start/activity, wait, stop.
The observers in the Libev also support the priority level.
The different types of observers are not explained in detail, just stick to some official examples here. Ev_io
Get standard input:
static void
STDIN_READABLE_CB (struct ev_loop *loop, ev_io *w, int revents)
{
ev_io_stop (loop, w); ...
re Ad from stdin this (or from W->FD) and handle any I/O errors
}
ev_io stdin_readable;
Ev_io_init (&stdin_readable, STDIN_READABLE_CB, Stdin_fileno, ev_read);
Ev_io_start (Loop, &stdin_readable);
Ev_timer
Create a timer that starts after 60s:
static void
ONE_MINUTE_CB (struct ev_loop *loop, ev_timer *w, int revents)
{
: One minute over, W is actually Stopped right here
}
ev_timer MyTimer;
Ev_timer_init (&mytimer, ONE_MINUTE_CB, 0.);
Ev_timer_start (Loop, &mytimer);
Create a 10s time-out timer:
static void
TIMEOUT_CB (struct ev_loop *loop, ev_timer *w, int revents)
{
: ten seconds without any activity< c3/>}
ev_timer MyTimer;
Ev_timer_init (&mytimer, TIMEOUT_CB, 0., 10.); /* Note, only repeat used *
/Ev_timer_again (&mytimer);/* Start timer */
Ev_run (loop, 0);
And in some piece of code this gets executed on any ' activity ':
//Reset the timeout to start ticking again at ten s Econds
Ev_timer_again (&mytimer);
Ev_periodic
Create a one-hour cycle timer:
static void
CLOCK_CB (struct ev_loop *loop, ev_periodic *w, int revents)
{
... it now a full hour (UTC, or TA I or whatever your clock follows)
}
ev_periodic Hourly_tick;
Ev_periodic_init (&hourly_tick, CLOCK_CB, 0., 3600., 0);
Ev_periodic_start (Loop, &hourly_tick);
or the custom cycle calculation method:
#include <math.h> static Ev_tstamp MY_SCHEDULER_CB (Ev_periodic *w, Ev_tstamp now) {return now + (3600.-Fmod
(now, 3600.)); } ev_periodic_init (&hourly_tick