mirror of https://gitee.com/openkylin/apr.git
85 lines
3.0 KiB
Plaintext
85 lines
3.0 KiB
Plaintext
The question has been asked multiple times, "Why is APR using Incomplete
|
|
types?" This document will try to explain that.
|
|
|
|
Incomplete types are used in APR because they can enforce portability, and
|
|
they make the APR developers job easier, as well as allowing APR to use native
|
|
types on all platforms. Imagine a scenario where APR wasn't using incomplete
|
|
types. The ap_file_t type would have to be defined as:
|
|
|
|
typedef struct ap_file_t {
|
|
ap_pool_t *pool
|
|
char *fname;
|
|
int eof_hit;
|
|
int pipe;
|
|
ap_interval_time_t timeout;
|
|
#ifdef WIN32
|
|
HANDLE file_handle;
|
|
DWORD dwFileAttributes;
|
|
#elif defined(OS2)
|
|
HFILE filedes;
|
|
HEV PipeSem
|
|
#else
|
|
int filedes;
|
|
int ungetchar;
|
|
#endif
|
|
|
|
#ifndef WIN32
|
|
int buffered;
|
|
ap_int32_flags
|
|
int isopen;
|
|
|
|
/* Stuff for buffered mode */
|
|
char *buffer;
|
|
int bufpos;
|
|
unsigned long dataRead;
|
|
int direction;
|
|
unsigned long filePtr;
|
|
ap_lock_t *mutex;
|
|
#endif
|
|
} ap_file_t;
|
|
|
|
This captures the essence of what is currently being defined for ap_file_t
|
|
using incomplete types. However, using this structure leads developers to
|
|
believe that they are safe accessing any of the fields in this structure.
|
|
This is not true. On some platforms, such as Windows, about half of the
|
|
structure disappears. We could combine some of these definitions with
|
|
macros, for example:
|
|
|
|
#ifdef WIN32
|
|
#define filetype HANDLE
|
|
#elif OS2
|
|
#define filetype HFILE
|
|
#else
|
|
#define filetype int
|
|
#endif
|
|
|
|
And then in the definition for ap_file_t, we could say:
|
|
filetype filedes;
|
|
|
|
This gets rid of some of the complexity, by moving it off to the side, but
|
|
it is still not safe for a programmers to access the filedes field directly
|
|
outside of APR, because the programmer has no way of knowing what the actual
|
|
type is. So for example printing the filedes using printf would yield wildly
|
|
varying results on Windows and OS2 when compared to Unix.
|
|
|
|
Another option also presents itself. Stick strictly to POSIX. This means
|
|
that all code can be shared on any POSIX compliant platform. The problem
|
|
with this is performance. One of the benefits to APR, is that it allows
|
|
developers to easily use native types on all platforms with the same code.
|
|
This has proven to provide a substantial performance boost on most non-Unix
|
|
platforms.
|
|
|
|
Having said all of that, sometimes incomplete types just don't make sense.
|
|
For example, the first implementation of time functions used incomplete types,
|
|
which added a layer of complexity that turned out to be unnecessary. If
|
|
a platform cannot provide a simple number that represents the number of seconds
|
|
elapsed since a specified date and time, then APR doesn't really want to
|
|
provide support for that platform.
|
|
|
|
APR is trying hard to provide a balance of incomplete and complete types,
|
|
but like all things, sometimes the developers make mistakes. If you are
|
|
using APR and find that there is an incomplete type that doesn't need to be
|
|
an incomplete type, please let us know, we are more than willing to listen
|
|
and design parts of APR that do not use incomplete types.
|
|
|