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
This commit is contained in:
122
include/wx/private/streamtempinput.h
Normal file
122
include/wx/private/streamtempinput.h
Normal file
@@ -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 <vadim@wxwindows.org>
|
||||
// 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
|
Reference in New Issue
Block a user