Source code is said to be portable if it compiles and runs in several environments without modification. Applications built on portable code have a potentially wide user base and streamlined development lifecycle, because teams don't have to maintain multiple code bases for disparate platforms.
One path to portability is to limit yourself to the language's base features. This is straightforward in languages such as Java and Perl, which include rich toolsets beyond the pure syntax. C and C++, on the other hand, don't address networking and other concepts required for real-world applications. Native-code portability involves messy preprocessor macros to detect and compensate for OS-specific oddities. Application teams either dedicate a portion of their staff to developing a portability layer in-house, or they acquire third-party solutions such as ACE or RogueWave.
Another contender in the arena of native-code portability is the Apache Portable Runtime (apr.apache.org). This C-based API provides abstractions ranging from memory management to telling time. APR developers focus on the OS-specific oddities so you can focus on your app. APR has been slowly developed over the years as part of the ubiquitous Apache web server, and has also been thoroughly road-tested in several other real-world applications. Better still, it is released under the cost-free, commercial-friendly Apache license.
In this article, I focus on APR's networking and polling routines. To that end, I present a straightforward network service, then revamp it a couple of times. The end result is an APR-based implementation of the Reactor pattern (www.cs.wustl.edu/~schmidt/patterns-ace.html). I built and tested the sample code under Fedora Core 4 using GCC 4.0.1 and APR 1.1.1 and 1.2.1. Because portability is the name of this game, I encourage you to build the sample code under your own operating systemLinux, Mac OS, Windows, or whateverto confirm that it works as advertised.
(To make the code easier to digest, I've made it tough to maintainit exposes APR in several places a production app would not; for example, the APRReactor class directly handles apr_pollfd_t values. In a real-world scenario, you'd do well to limit how far a third-party toolkit spreads throughout your app. Hiding such an API behind abstractions and interfaces makes it easier to swap out or remove later on.)