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.
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/
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
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++
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.
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();
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
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