You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by rb...@locus.apache.org on 2000/05/19 23:44:11 UTC

cvs commit: apache-2.0/src/lib/apr/docs incomplete_types non_apr_programs

rbb         00/05/19 14:44:11

  Added:       src/lib/apr/docs incomplete_types non_apr_programs
  Log:
  Add two APR docs.  The first talks about why we are using incomplete
  types.  The second talks about using APR'ized programs with non-APR'ized
  programs.
  
  Revision  Changes    Path
  1.1                  apache-2.0/src/lib/apr/docs/incomplete_types
  
  Index: incomplete_types
  ===================================================================
  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 essense 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 defintion 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 specifed 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.
  
  
  
  
  1.1                  apache-2.0/src/lib/apr/docs/non_apr_programs
  
  Index: non_apr_programs
  ===================================================================
  How do I use APR'ized programs in connection with programs that don't
  use APR?  These darn incomplete types don't let me fill out the APR types.
  
  The APR developers acknowledge that most programs are not using APR, and
  we don't expect them to migrate to using APR just because APR has been
  released.  So, we have provided a way for non-APR'ized programs to interact
  very cleanly with APR.
  
  There are a set of programs, all documented in apr_portable.h, which allow
  a programmer to either get a native type from an APR type, or to setup an
  APR type from a native type.
  
  For example, if you are writing an add-on to another program that does not use
  APR for file I/O, but you (in your infinite wisdom) want to use APR to make
  sure your section is portable.  Assume the program provides a type foo_t with
  a file descriptor in it (fd).
  
  void function_using_apr(foo_t non_apr_struct, ap_pool_t *p)
  {
      ap_file_t *apr_file = NULL;
  
      ap_put_os_file(&apr_file, &non_apr_struct->fd, p);
  
      ...
  }
  
  There are portable functions for each APR incomplete type.  They are all 
  called ap_put_os_foobar(), and they each take the same basic arguments, a
  pointer to a pointer to the incomplete type (the last pointer in that list 
  should be NULL), a pointer to the native type, and a pool.  Each of these can
  be found in apr_portable.h.
  
  If you have to do the exact opposite (take an APR type and convert it to a 
  native type, there are functions for that too.  For example:
  
  void function_not_using_apr(apr_file_t *apr_file)
  {
      int unix_file_desc;
  
      ap_get_os_file(&unix_file_desc, apr_file);
     
      ...
  }
  
  For each ap_put_os_foobar, there is a corresponding ap_get_os_file.  These are
  also documented in apr_portable.h.