Asynchronous programming with libev

libev

libev is a library that handles asynchronous processing and is also used in node.js and so on. Originally, Unix-like systems had an asynchronous process called select () that handles file descriptors, but this limited the number of file descriptors that could be monitored. After that, unlimited poll () was developed, epoll () which accelerated poll () was developed in Linux, and KQUEUE was developed in BSD. And a library called libev was developed to absorb these differences.

Installation

brew install libev

The current version will be installed in the following location: This entry treats this path as is, without going through the library path.

/usr/local/Cellar/libev/4.15/

xcode settings

Add the following to "Header Search Paths" in the project Build Settings.

/usr/local/Cellar/libev/4.15/include/

Add the following to "Library Search Paths" in the project Build Settings.

/usr/local/Cellar/libev/4.15/lib/

Add the following to "Linking" in the Build Settings of the project.

-lev
-ObjC
-all_load

Basic usage

First, declare the event loop object. Then declare a watch object for the type of event you want to watch and associate the callback with the file descriptor. Finally, the event loop is associated with the watch object and the loop is started at the same time.

The following is a slight modification of the official sample.

#include <ev.h>
#include <iostream>

static void stdin_cb (EV_P_ ev_io *w, int revents)
{
    std::cout << "stdin ready\n";
    
    // I/Disassociate O from loop.
    ev_io_stop (EV_A_ w);
    
    //Break the event loop.
    ev_unloop (EV_A_ EVUNLOOP_ALL);
}

static void timeout_cb (EV_P_ ev_timer *w, int revents)
{
    std::cout << "timeout\n";

    //Stop the timer.
    ev_timer_stop (EV_A_ w);
    
    //Break the event loop.
    ev_unloop (EV_A_ EVUNLOOP_ONE);
}

int main(int argc, const char * argv[])
{
    //Create an event loop.
    struct ev_loop *loop = ev_loop_new (0);

    // I/O watch object.
    ev_io stdin_watcher;
    
    // I/For O watch objects
    //Associate callbacks with FDs with event types.
    ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
    
    // I/Associate an event loop with an O watch object.
    ev_io_start (loop, &stdin_watcher);


    //Create a timer object.
    ev_timer timeout_watcher;
    
    //Associate a callback with a timer object and specify a timeout(Repeat in 5 seconds 0).
    ev_timer_init (&timeout_watcher, timeout_cb, 5, 0.);
    
    //Associate an event loop with a timer object.
    ev_timer_start (loop, &timeout_watcher);
    
    //Loop start.
    ev_loop (loop, 0);
    
    std::cout << "end¥n";
    
    //Discard the created event loop
    ev_loop_destroy(loop);
    
    return 0;
}

Since you can't interact with the command line with xcode, try building with gcc using the following method.

# gcc -o test test.cpp -lev -I/usr/local/Cellar/libev/4.15/include/ -L/usr/local/Cellar/libev/4.15/lib/ -lstdc++

Creating an event loop

The official sample uses ev_default_loop (), but it doesn't seem to be thread-safe, so in the above example we created an event loop with ev_loop_new (0) and destroyed it with ev_loop_destroy (loop).

The argument specifies which asynchronous process to use when creating this event loop. The default is 0, which is set automatically.

Asynchronous technology used by libev

You can see what is being used by the backend with the following method.

unsigned int ev_supported_backends ()
  EVBACKEND_SELECT  = 0x00000001U, /* about anywhere */
  EVBACKEND_POLL    = 0x00000002U, /* !win */
  EVBACKEND_EPOLL   = 0x00000004U, /* linux */
  EVBACKEND_KQUEUE  = 0x00000008U, /* bsd */
  EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */
  EVBACKEND_PORT    = 0x00000020U, /* solaris 10 */
  EVBACKEND_ALL     = 0x0000003FU, /* all known backends */
  EVBACKEND_MASK    = 0x0000FFFFU  /* all future backends */

You can get the recommended asynchronous processing with the following method.

unsigned int ev_recommended_backends();

Events that can be monitored

What can be handled depends on the type of monitoring object.

EV_READ EV_WRITE EV_TIMEOUT EV_PERIODIC EV_SIGNAL EV_CHILD EV_STAT EV_IDLE EV_PREPARE EV_CHECK EV_EMBED EV_FORK EV_ASYNC EV_ERROR

Monitoring object type

ev_io ev_timer ev_periodic ev_signal ev_stat ev_idle ev_embed ev_fork ev_async

Next time I will deal with sockets.

Recommended Posts

Asynchronous programming with libev # 2
Asynchronous programming with libev
Asynchronous programming with libev # 3
3. 3. AI programming with Python
Python programming with Atom
Competitive programming with python
Shader programming with pyOpenGL
Linear Programming with PuLP
Programming with Python Flask
Try programming with a shell!
Try GUI programming with Hy
Programming education game with SenseHAT
Network programming with Python Scapy
[Python] Object-oriented programming learned with Pokemon
Easy Python + OpenCV programming with Canopy
[Python] Asynchronous request with async / await
Competitive programming with python Local environment settings
GUI programming with kivy ~ Part 4 Various buttons ~
A complete understanding of Python's asynchronous programming
Programming normally with Node-RED programming on Raspberry Pi 3
Do embedded programming with test-driven development with googletest
Sound programming with Go (super introductory level)
What you can do with programming skills