]>
git.saurik.com Git - wxWidgets.git/blob - src/common/execcmn.cpp
   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 
  10 // Copyright:   (c) 2002 Vadim Zeitlin <vadim@wxwindows.org> 
  11 // Licence:     wxWindows licence 
  12 /////////////////////////////////////////////////////////////////////////////// 
  14 #ifndef _WX_WXEXEC_CPP_ 
  15 #define _WX_WXEXEC_CPP_ 
  17 // this file should never be compiled directly, just included by other code 
  18 #ifndef _WX_USED_BY_WXEXECUTE_ 
  19     #error "You should never directly build this file!" 
  22 // ---------------------------------------------------------------------------- 
  23 // wxStreamTempInputBuffer 
  24 // ---------------------------------------------------------------------------- 
  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. 
  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() 
  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)... 
  45 class wxStreamTempInputBuffer
 
  48     wxStreamTempInputBuffer(); 
  50     // call to associate a stream with this buffer, otherwise nothing happens 
  52     void Init(wxPipeInputStream 
*stream
); 
  54     // check for input on our stream and cache it in our buffer if any 
  57     ~wxStreamTempInputBuffer(); 
  60     // the stream we're buffering, if NULL we don't do anything at all 
  61     wxPipeInputStream 
*m_stream
; 
  63     // the buffer of size m_size (NULL if m_size == 0) 
  66     // the size of the buffer 
  69     DECLARE_NO_COPY_CLASS(wxStreamTempInputBuffer
) 
  72 inline wxStreamTempInputBuffer::wxStreamTempInputBuffer() 
  79 inline void wxStreamTempInputBuffer::Init(wxPipeInputStream 
*stream
) 
  85 void wxStreamTempInputBuffer::Update() 
  87     if ( m_stream 
&& m_stream
->CanRead() ) 
  89         // realloc in blocks of 4Kb: this is the default (and minimal) buffer 
  90         // size of the Unix pipes so it should be the optimal step 
  92         // NB: don't use "static int" in this inline function, some compilers 
  93         //     (e.g. IBM xlC) don't like it 
  94         enum { incSize 
= 4096 }; 
  96         void *buf 
= realloc(m_buffer
, m_size 
+ incSize
); 
  99             // don't read any more, we don't have enough memory to do it 
 102         else // got memory for the buffer 
 105             m_stream
->Read((char *)m_buffer 
+ m_size
, incSize
); 
 106             m_size 
+= m_stream
->LastRead(); 
 112 wxStreamTempInputBuffer::~wxStreamTempInputBuffer() 
 116         m_stream
->Ungetch(m_buffer
, m_size
); 
 121 #endif // _WX_WXEXEC_CPP_