home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / execcmn.cpp < prev    next >
C/C++ Source or Header  |  2002-11-04  |  4KB  |  116 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name:        common/wxexec.cpp
  3. // Purpose:     defines wxStreamTempInputBuffer which is used by Unix and MSW
  4. //              implementations of wxExecute; this file is only used by the
  5. //              library and never by the user code
  6. // Author:      Vadim Zeitlin
  7. // Modified by:
  8. // Created:     20.08.02
  9. // RCS-ID:      $Id: execcmn.cpp,v 1.1.2.1 2002/11/04 00:40:54 VZ Exp $
  10. // Copyright:   (c) 2002 Vadim Zeitlin <vadim@wxwindows.org>
  11. // Licence:     wxWindows licence
  12. ///////////////////////////////////////////////////////////////////////////////
  13.  
  14. #ifndef _WX_WXEXEC_CPP_
  15. #define _WX_WXEXEC_CPP_
  16.  
  17. // this file should never be compiled directly, just included by other code
  18. #ifndef _WX_USED_BY_WXEXECUTE_
  19.     #error "Please don't exclude this file from build!"
  20. #endif
  21.  
  22. // ----------------------------------------------------------------------------
  23. // wxStreamTempInputBuffer
  24. // ----------------------------------------------------------------------------
  25.  
  26. /*
  27.    wxStreamTempInputBuffer is a hack which we need to solve the problem of
  28.    executing a child process synchronously with IO redirecting: when we do
  29.    this, the child writes to a pipe we open to it but when the pipe buffer
  30.    (which has finite capacity, e.g. commonly just 4Kb) becomes full we have to
  31.    read data from it because the child blocks in its write() until then and if
  32.    it blocks we are never going to return from wxExecute() so we dead lock.
  33.  
  34.    So here is the fix: we now read the output as soon as it appears into a temp
  35.    buffer (wxStreamTempInputBuffer object) and later just stuff it back into
  36.    the stream when the process terminates. See supporting code in wxExecute()
  37.    itself as well.
  38.  
  39.    Note that this is horribly inefficient for large amounts of output (count
  40.    the number of times we copy the data around) and so a better API is badly
  41.    needed! However it's not easy to devise a way to do this keeping backwards
  42.    compatibility with the existing wxExecute(wxEXEC_SYNC)...
  43. */
  44.  
  45. class wxStreamTempInputBuffer
  46. {
  47. public:
  48.     wxStreamTempInputBuffer();
  49.  
  50.     // call to associate a stream with this buffer, otherwise nothing happens
  51.     // at all
  52.     void Init(wxPipeInputStream *stream);
  53.  
  54.     // check for input on our stream and cache it in our buffer if any
  55.     void Update();
  56.  
  57.     ~wxStreamTempInputBuffer();
  58.  
  59. private:
  60.     // the stream we're buffering, if NULL we don't do anything at all
  61.     wxPipeInputStream *m_stream;
  62.  
  63.     // the buffer of size m_size (NULL if m_size == 0)
  64.     void *m_buffer;
  65.  
  66.     // the size of the buffer
  67.     size_t m_size;
  68. };
  69.  
  70. inline wxStreamTempInputBuffer::wxStreamTempInputBuffer()
  71. {
  72.     m_stream = NULL;
  73.     m_buffer = NULL;
  74.     m_size = 0;
  75. }
  76.  
  77. inline void wxStreamTempInputBuffer::Init(wxPipeInputStream *stream)
  78. {
  79.     m_stream = stream;
  80. }
  81.  
  82. void wxStreamTempInputBuffer::Update()
  83. {
  84.     if ( m_stream && m_stream->CanRead() )
  85.     {
  86.         // realloc in blocks of 4Kb: this is the default (and minimal) buffer
  87.         // size of the Unix pipes so it should be the optimal step
  88.         static const size_t incSize = 4096;
  89.  
  90.         void *buf = realloc(m_buffer, m_size + incSize);
  91.         if ( !buf )
  92.         {
  93.             // don't read any more, we don't have enough memory to do it
  94.             m_stream = NULL;
  95.         }
  96.         else // got memory for the buffer
  97.         {
  98.             m_buffer = buf;
  99.             m_stream->Read((char *)m_buffer + m_size, incSize);
  100.             m_size += m_stream->LastRead();
  101.         }
  102.     }
  103. }
  104.  
  105. wxStreamTempInputBuffer::~wxStreamTempInputBuffer()
  106. {
  107.     if ( m_buffer )
  108.     {
  109.         m_stream->Ungetch(m_buffer, m_size);
  110.         free(m_buffer);
  111.     }
  112. }
  113.  
  114. #endif // _WX_WXEXEC_CPP_
  115.  
  116.