From: Vadim Zeitlin Date: Wed, 3 Jul 2013 00:27:02 +0000 (+0000) Subject: No changes, move wxStreamTempInputBuffer to a header file. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/9b70925d3e82d58cf8082ad69c6f67ca6fd61895 No changes, move wxStreamTempInputBuffer to a header file. Get rid of the surprising src/common/execcmn.cpp which had a .cpp extension but was supposed to be used as an included file only and move its contents to a new private header to make using wxStreamTempInputBuffer class simpler. See #10258. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74337 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/private/streamtempinput.h b/include/wx/private/streamtempinput.h new file mode 100644 index 0000000000..72f3957ec3 --- /dev/null +++ b/include/wx/private/streamtempinput.h @@ -0,0 +1,122 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/private/streamtempinput.h +// Purpose: defines wxStreamTempInputBuffer which is used by Unix and MSW +// implementations of wxExecute; this file is only used by the +// library and never by the user code +// Author: Vadim Zeitlin +// Modified by: Rob Bresalier +// Created: 2013-05-04 +// RCS-ID: $Id$ +// Copyright: (c) 2002 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PRIVATE_STREAMTEMPINPUT_H +#define _WX_PRIVATE_STREAMTEMPINPUT_H + +#include "wx/private/pipestream.h" + +// ---------------------------------------------------------------------------- +// wxStreamTempInputBuffer +// ---------------------------------------------------------------------------- + +/* + wxStreamTempInputBuffer is a hack which we need to solve the problem of + executing a child process synchronously with IO redirecting: when we do + this, the child writes to a pipe we open to it but when the pipe buffer + (which has finite capacity, e.g. commonly just 4Kb) becomes full we have to + read data from it because the child blocks in its write() until then and if + it blocks we are never going to return from wxExecute() so we dead lock. + + So here is the fix: we now read the output as soon as it appears into a temp + buffer (wxStreamTempInputBuffer object) and later just stuff it back into + the stream when the process terminates. See supporting code in wxExecute() + itself as well. + + Note that this is horribly inefficient for large amounts of output (count + the number of times we copy the data around) and so a better API is badly + needed! However it's not easy to devise a way to do this keeping backwards + compatibility with the existing wxExecute(wxEXEC_SYNC)... +*/ +class wxStreamTempInputBuffer +{ +public: + wxStreamTempInputBuffer() + { + m_stream = NULL; + m_buffer = NULL; + m_size = 0; + } + + // call to associate a stream with this buffer, otherwise nothing happens + // at all + void Init(wxPipeInputStream *stream) + { + wxASSERT_MSG( !m_stream, wxS("Can only initialize once") ); + + m_stream = stream; + } + + // check for input on our stream and cache it in our buffer if any + // + // return true if anything was done + bool Update() + { + if ( !m_stream || !m_stream->CanRead() ) + return false; + + // realloc in blocks of 4Kb: this is the default (and minimal) buffer + // size of the Unix pipes so it should be the optimal step + // + // NB: don't use "static int" in this inline function, some compilers + // (e.g. IBM xlC) don't like it + enum { incSize = 4096 }; + + void *buf = realloc(m_buffer, m_size + incSize); + if ( !buf ) + return false; + + m_buffer = buf; + m_stream->Read((char *)m_buffer + m_size, incSize); + m_size += m_stream->LastRead(); + + return true; + } + + // check if can continue reading from the stream, this is used to disable + // the callback once we can't read anything more + bool Eof() const + { + // If we have no stream, always return true as we can't read any more. + return !m_stream || m_stream->Eof(); + } + + // dtor puts the data buffered during this object lifetime into the + // associated stream + ~wxStreamTempInputBuffer() + { + if ( m_buffer ) + { + m_stream->Ungetch(m_buffer, m_size); + free(m_buffer); + } + } + + const void *GetBuffer() const { return m_buffer; } + + size_t GetSize() const { return m_size; } + +private: + // the stream we're buffering, if NULL we don't do anything at all + wxPipeInputStream *m_stream; + + // the buffer of size m_size (NULL if m_size == 0) + void *m_buffer; + + // the size of the buffer + size_t m_size; + + wxDECLARE_NO_COPY_CLASS(wxStreamTempInputBuffer); +}; + +#endif // _WX_PRIVATE_STREAMTEMPINPUT_H diff --git a/src/common/execcmn.cpp b/src/common/execcmn.cpp deleted file mode 100644 index 1d23ed6f1c..0000000000 --- a/src/common/execcmn.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Name: src/common/execcmn.cpp -// Purpose: defines wxStreamTempInputBuffer which is used by Unix and MSW -// implementations of wxExecute; this file is only used by the -// library and never by the user code -// Author: Vadim Zeitlin -// Modified by: -// Created: 20.08.02 -// RCS-ID: $Id$ -// Copyright: (c) 2002 Vadim Zeitlin -// Licence: wxWindows licence -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _WX_WXEXEC_CPP_ -#define _WX_WXEXEC_CPP_ - -// this file should never be compiled directly, just included by other code -#ifndef _WX_USED_BY_WXEXECUTE_ - #error "You should never directly build this file!" -#endif - -// ---------------------------------------------------------------------------- -// wxStreamTempInputBuffer -// ---------------------------------------------------------------------------- - -/* - wxStreamTempInputBuffer is a hack which we need to solve the problem of - executing a child process synchronously with IO redirecting: when we do - this, the child writes to a pipe we open to it but when the pipe buffer - (which has finite capacity, e.g. commonly just 4Kb) becomes full we have to - read data from it because the child blocks in its write() until then and if - it blocks we are never going to return from wxExecute() so we dead lock. - - So here is the fix: we now read the output as soon as it appears into a temp - buffer (wxStreamTempInputBuffer object) and later just stuff it back into - the stream when the process terminates. See supporting code in wxExecute() - itself as well. - - Note that this is horribly inefficient for large amounts of output (count - the number of times we copy the data around) and so a better API is badly - needed! However it's not easy to devise a way to do this keeping backwards - compatibility with the existing wxExecute(wxEXEC_SYNC)... -*/ - -class wxStreamTempInputBuffer -{ -public: - wxStreamTempInputBuffer(); - - // call to associate a stream with this buffer, otherwise nothing happens - // at all - void Init(wxPipeInputStream *stream); - - // check for input on our stream and cache it in our buffer if any - // - // return true if anything was done - bool Update(); - - ~wxStreamTempInputBuffer(); - -private: - // the stream we're buffering, if NULL we don't do anything at all - wxPipeInputStream *m_stream; - - // the buffer of size m_size (NULL if m_size == 0) - void *m_buffer; - - // the size of the buffer - size_t m_size; - - wxDECLARE_NO_COPY_CLASS(wxStreamTempInputBuffer); -}; - -inline wxStreamTempInputBuffer::wxStreamTempInputBuffer() -{ - m_stream = NULL; - m_buffer = NULL; - m_size = 0; -} - -inline void wxStreamTempInputBuffer::Init(wxPipeInputStream *stream) -{ - m_stream = stream; -} - -inline -bool wxStreamTempInputBuffer::Update() -{ - if ( !m_stream || !m_stream->CanRead() ) - return false; - - // realloc in blocks of 4Kb: this is the default (and minimal) buffer - // size of the Unix pipes so it should be the optimal step - // - // NB: don't use "static int" in this inline function, some compilers - // (e.g. IBM xlC) don't like it - enum { incSize = 4096 }; - - void *buf = realloc(m_buffer, m_size + incSize); - if ( !buf ) - { - // don't read any more, we don't have enough memory to do it - m_stream = NULL; - } - else // got memory for the buffer - { - m_buffer = buf; - m_stream->Read((char *)m_buffer + m_size, incSize); - m_size += m_stream->LastRead(); - } - - return true; -} - -inline -wxStreamTempInputBuffer::~wxStreamTempInputBuffer() -{ - if ( m_buffer ) - { - m_stream->Ungetch(m_buffer, m_size); - free(m_buffer); - } -} - -#endif // _WX_WXEXEC_CPP_ - diff --git a/src/msw/utilsexc.cpp b/src/msw/utilsexc.cpp index cd4f5b86b2..1a4a918c07 100644 --- a/src/msw/utilsexc.cpp +++ b/src/msw/utilsexc.cpp @@ -202,10 +202,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxExecuteModule, wxModule) #if wxUSE_STREAMS && !defined(__WXWINCE__) #include "wx/private/pipestream.h" - -// define this to let wxexec.cpp know that we know what we're doing -#define _WX_USED_BY_WXEXECUTE_ -#include "../common/execcmn.cpp" +#include "wx/private/streamtempinput.h" // ---------------------------------------------------------------------------- // wxPipe represents a Win32 anonymous pipe diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index fb2854f847..5722e84260 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -64,10 +64,7 @@ #if HAS_PIPE_STREAMS #include "wx/private/pipestream.h" - -// define this to let wxexec.cpp know that we know what we're doing -#define _WX_USED_BY_WXEXECUTE_ -#include "../common/execcmn.cpp" +#include "wx/private/streamtempinput.h" #endif // HAS_PIPE_STREAMS