3.3. Event Loop

3.3.1. Concepts

  • Event loops
  • Asynchronous event handling
  • File descriptor based IO multiplexing

3.3.2. Assignment

  • Create an event loop module implementation
  • Use the epoll system call
  • Make a generic implementation with user callback and data pointer
  • Create a header file for reuse in other programs

3.3.3. Module API

#ifndef EVLOOP_HDR
#define EVLOOP_HDR

#define EVLOOP_POLL_READ      0x01
#define EVLOOP_POLL_WRITE     0x02
#define EVLOOP_POLL_HUP       0x04
#define EVLOOP_POLL_POLLPRI   0x08

struct evloop_ctx;
struct evloop_event;

typedef void(*evloop_fd_cb)(int fd, short revents, void *data);

// creates a new event loop context
int evloop_create(struct evloop_ctx **ctx);
// starts the event loop context, running a continuous loop inside
int evloop_run(struct evloop_ctx *ctx);
// pause the event loop
int evloop_halt(struct evloop_ctx *ctx);
// clean up and remove the event loop context
int evloop_destroy(struct evloop_ctx *ctx);

// create a fd event and add it to the evloop context ctx
int evloop_event_add_fd(struct evloop_ctx *ctx, struct evloop_event **ev, int fd,
                        int events, evloop_cb cb, void *data);
// clean up and remove the event
int evloop_event_remove(struct evloop_event *ev);

#endif

3.3.4. Example

#include "evloop.h"
#include "nsock.h"

void socket_cb(int fd, short revents, void *data)
{
        int ret = 0;
        char buf[1024] = "";
        char reply[1024] = "";

        ret = nsock_read(fd, buf, 1024);
        // ...

        // process and build reply

        ret = nsock_write(fd, reply, strlen(reply));
        // ...

        return;
}

int main(int argc, char **argv)
{
        int ret = 0;
        int sfd = -1;
        struct evloop_ctx *evlctx = NULL;
        struct evloop_event *sev = NULL;

        sfd = nsock_open("192.168.1.100", 5555);
        // ...

        ret = evloop_create(&evlctx);
        // ...

        ret = evloop_event_add(evlctx, &sev, sfd, EVLOOP_POLL_READ, socket_cb, NULL);
        // ...

        return evloop_run(evlctx);
}

3.3.5. Questions

  • What open source libraries exist that provide event loop features?
  • How to add support for timers in the API?
  • How to add support for signals in the API?