Factor Language Blog

What's up with non-blocking I/O APIs?

Wednesday, January 23, 2008

On Linux, epoll() works with ttys, pipes and sockets, but not files.

On Mac OS X, kqueue() works with sockets but not ttys.

On Windows, GetQueuedCompletionStatus() works with everything except for the console.

I think it is sad that non-blocking I/O APIs are typically added as afterthoughts. Instead, operating system I/O APIs should be designed around the notion of asynchronous events; blocking streams can be done in user-space with coroutines or continuations.

However what’s done is done and we have to support today’s OSes. On Mac OS X, the main reason I’m looking at kqueue() is to support non-blocking process exit notification as well as file system change notification. So I can add the kqueue file descriptor to the select() set and use select() for everything else.

On Linux, I’m not sure there’s any point using epoll(). Perhaps I can throw sockets there and use select() for everything else, but this may just end up being more complexity than is necessary.

Anyway, support for the more advanced non-blocking I/O APIs available on Mac OS X and Linux was one of my big to do list items for Factor 1.0. Not only did it take less effort to implement than I thought, but the payoff doesn’t seem so great either. At least we can now implement file change notification on OS X.