Recently I’ve been experimenting with the concept of a high-performance (high parallelism, high concurrency, low CPU/memory footprint) TCP server in Ada. Developing on top of Linux, you cannot help avoid the epoll(7) I/O event notification system.

Unlike my previous post on dynamic task creation in Ada, this post won’t have much in the way of sample code and walk-through. Mostly because I didn’t want to spend the entire post explaining epoll(7) concepts.

If you’re currently unfamiliar with epoll, I found this post from banu.com interesting and useful. In general, I think that it is very useful to understand how both epoll(7) and its BSD-friendly pal kqueue(2) work, and how the two have influenced evented I/O systems that have become popular in the past few years.

For my experiment, the primary challenge with using epoll(7) is wrapping the C code with Ada, which on its face this isn’t terribly difficult. That said, mapping C arrays and other stupid pointer tricks that C libraries are prone to using, can make writing an Ada binding much more difficult. I don’t intend to dive too deep into how one can create such a binding since I think Felix Krause’s post on writing thin/thick C bindings in Ada is a pretty good introduction on that subject. Personally I prefer “thicker” bindings for use in Ada, just as I expect Ruby libraries to abstract away the more fickle aspects of the underlying C API.

What I did want to share in this post was the actual working results of my tinkering, which can be found here, on GitHub.

The basic flow of the program (found in main.adb) is similar to the example found in the epoll(7) man page, in that it sets up the epollfd, binds the listening to it and then waits for Epoll.Wait to return with an array of socket descriptors which have activity on them.

My next step is to combine this basic epoll binding with my previous task related code and create a TCP server which uses a task pool to perform “work” on the incoming sockets given to it by an epoll-listener task.