incomplete_types revision 362181
1The question has been asked multiple times, "Why is APR using Incomplete 2types?" This document will try to explain that. 3 4Incomplete types are used in APR because they can enforce portability, and 5they make the APR developers job easier, as well as allowing APR to use native 6types on all platforms. Imagine a scenario where APR wasn't using incomplete 7types. The ap_file_t type would have to be defined as: 8 9typedef struct ap_file_t { 10 ap_pool_t *pool 11 char *fname; 12 int eof_hit; 13 int pipe; 14 ap_interval_time_t timeout; 15#ifdef WIN32 16 HANDLE file_handle; 17 DWORD dwFileAttributes; 18#elif defined(OS2) 19 HFILE filedes; 20 HEV PipeSem 21#else 22 int filedes; 23 int ungetchar; 24#endif 25 26#ifndef WIN32 27 int buffered; 28 ap_int32_flags 29 int isopen; 30 31 /* Stuff for buffered mode */ 32 char *buffer; 33 int bufpos; 34 unsigned long dataRead; 35 int direction; 36 unsigned long filePtr; 37 ap_lock_t *mutex; 38#endif 39} ap_file_t; 40 41This captures the essence of what is currently being defined for ap_file_t 42using incomplete types. However, using this structure leads developers to 43believe that they are safe accessing any of the fields in this structure. 44This is not true. On some platforms, such as Windows, about half of the 45structure disappears. We could combine some of these definitions with 46macros, for example: 47 48#ifdef WIN32 49#define filetype HANDLE 50#elif OS2 51#define filetype HFILE 52#else 53#define filetype int 54#endif 55 56And then in the definition for ap_file_t, we could say: 57 filetype filedes; 58 59This gets rid of some of the complexity, by moving it off to the side, but 60it is still not safe for a programmers to access the filedes field directly 61outside of APR, because the programmer has no way of knowing what the actual 62type is. So for example printing the filedes using printf would yield wildly 63varying results on Windows and OS2 when compared to Unix. 64 65Another option also presents itself. Stick strictly to POSIX. This means 66that all code can be shared on any POSIX compliant platform. The problem 67with this is performance. One of the benefits to APR, is that it allows 68developers to easily use native types on all platforms with the same code. 69This has proven to provide a substantial performance boost on most non-Unix 70platforms. 71 72Having said all of that, sometimes incomplete types just don't make sense. 73For example, the first implementation of time functions used incomplete types, 74which added a layer of complexity that turned out to be unnecessary. If 75a platform cannot provide a simple number that represents the number of seconds 76elapsed since a specified date and time, then APR doesn't really want to 77provide support for that platform. 78 79APR is trying hard to provide a balance of incomplete and complete types, 80but like all things, sometimes the developers make mistakes. If you are 81using APR and find that there is an incomplete type that doesn't need to be 82an incomplete type, please let us know, we are more than willing to listen 83and design parts of APR that do not use incomplete types. 84 85