libevent is a popular notification library. The API is elegant. And the performance is good. The bad thing is that there is no much information about its implementation. After failing to find such information on the web, I decide to take a look at the source code of libevent. I have analyzed?its default behavior of the following libevent sample code on linux. I am using ubuntu.
?
?
#include <sys/stat.h> #include <sys/queue.h> #include <unistd.h> #include <sys/time.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include "event.h" void fifo_read(int fd, short event, void *arg) { char buf[255]; int len; struct event *ev = arg; fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %p\n", fd, event, arg); len = read(fd, buf, sizeof(buf) - 1); if (len == -1) { perror("read"); return; } else if (len == 0) { fprintf(stderr, "Connectionless closed\n"); return; } buf[len] = '\0'; fprintf(stdout, "Read: %s\n", buf); /*event_add(ev, NULL);*/ } int main(int argc, const char *argv[]) { struct event evfifo; struct stat st; char *fifo = "event.fifo"; int socket; if (lstat(fifo, &st) == 0) { if ((st.st_mode & S_IFMT) == S_IFREG) { errno = EEXIST; perror("lstat"); exit(1); } } unlink(fifo); if (mkfifo(fifo, 0600) == -1) { perror("mkfifo"); exit(1); } socket = open(fifo, O_RDWR | O_NONBLOCK, 0); if (socket == -1) { perror("open"); exit(1); } fprintf(stderr, "Write data to %s\n", fifo); event_init(); event_set(&evfifo, socket, EV_READ | EV_PERSIST, fifo_read, &evfifo); event_add(&evfifo, NULL); fprintf(stderr, "begin dispatch\n"); event_loop(0); fprintf(stderr, "end dispatch\n"); return 0; }?
On ubuntu, epoll is used as?the internal event mechanism. event_loop is a wrapper of?event_base_loop. For my case, here is the pseudo code of?event_base_loop.
?
event_base_loop
?? loop
?? ? ?epoll_wait // timeout is set to -1
?
You can see that event_base_loop will bock on epoll_wait indefinitely if no IO happens.
?
?
?