More than 30 years ago, Brian Kernighan and Dennis Ritchie invented C to develop their Unix operating system. Today, C is still the language of systems software development. There could be many reasons for this long-lasting popularity, but many problems are now emerging as the system softwares are getting complex and evolving rapidly.
In this project, we envision a C++ library designed specifically for systems software development. One of the goals of JTL is to bring codes, that would otherwise end up with C macros, into the realm of C++ formalism of strong type-safety. To achieve this without hurting performance, we extensively use C++ templates.
C preprocessor directives are notorious for their penchant for inducing bugs that are hard to detect. For instance, C macros (i.e.,
#define) bypass all the type-checking until the macros are actually expanded. Oftentimes, the result of this expansion is not what the programmer originally intended. For another example, C conditional compilation directives (i.e.,
#ifdef) make the compiler simply ignore the code excluded by the conditionals. This leaves some codes totally unchecked, potentially leaving bugs in the code.
Despite these shortcomings, many systems software implementations use these directives extensively. To see some examples of this, you need only to take a look at Linux or Xen hypervisor code: the deeper you step-in, the more you find macros. There are many reasons for this. Some are historical, but the major technical reason is this: macros and conditionals can provide efficient methods to introduce a code-level abstraction layer (as in ‘wrapper’) in the face of real-world’s needs to satisfy ever-evolving requirements. This reason is actually highly relevant in systems software, where the performance is a critical issue and the system must support for hardware/software diversity.
The removal of these error-prone directives, therefore, has been a peripheral issue. The arguments in favor of the status quo can be summarized as follows.
- C macros are fast and give more controls to programmer. Other ‘explicit’ layering hurt either performance or portability.
- The potential bugs can be eliminated as the code matures, which is quite true if the code is open-sourced.
- Simple ‘hacks’ using macros can solve the problems. So why bother?
This work is motivated by the following counter-arguments.
- Retaining strong type-safety, C++ can provide the same benefits to programmer through template and specialization.
- Reusing macro-laden code in other projects leads to new potential bugs since macros are fragile and context-sensitive.
- The macro hacks are not generally portable. Also, we need to beware of slippery slope of using macros for quick fix.
One of the goals of JTL is to bring codes, that would otherwise end up with C macros, into the realm of C++ formalism of strong type-safety. Specifically, we want to achieve this without hurting performance. Therefore, we extensively use C++ template. The end result is a solid library of low-level systems code that can be easily reused for systems software development.
Here we exploit two highlighted features of C++: template and specialization. C++ template can replace most of the macro definitions. This can be done without hurting performance because the compiler can collapse (optimize) most of the type conversions at compile time. C++ specialization allows programmers to redefine functions for a particular type instance, replacing conditional compilation directives in C.
- Jisoo Yang