1 /////////////////////////////////////////////////////////////////////////////// 2 // Name: wx/unix/private/executeiohandler.h 3 // Purpose: IO handler class for the FD used by wxExecute() under Unix 4 // Author: Rob Bresalier, Vadim Zeitlin 5 // Created: 2013-01-06 6 // Copyright: (c) 2013 Rob Bresalier, Vadim Zeitlin 7 // Licence: wxWindows licence 8 /////////////////////////////////////////////////////////////////////////////// 9 10 #ifndef _WX_UNIX_PRIVATE_EXECUTEIOHANDLER_H_ 11 #define _WX_UNIX_PRIVATE_EXECUTEIOHANDLER_H_ 12 13 #include "wx/private/streamtempinput.h" 14 15 // This class handles IO events on the pipe FD connected to the child process 16 // stdout/stderr and is used by wxExecute(). 17 // 18 // Currently it can derive from either wxEventLoopSourceHandler or 19 // wxFDIOHandler depending on the kind of dispatcher/event loop it is used 20 // with. In the future, when we get rid of wxFDIOHandler entirely, it will 21 // derive from wxEventLoopSourceHandler only. 22 template <class T> 23 class wxExecuteIOHandlerBase : public T 24 { 25 public: wxExecuteIOHandlerBase(int fd,wxStreamTempInputBuffer & buf)26 wxExecuteIOHandlerBase(int fd, wxStreamTempInputBuffer& buf) 27 : m_fd(fd), 28 m_buf(buf) 29 { 30 m_callbackDisabled = false; 31 } 32 33 // Called when the associated descriptor is available for reading. OnReadWaiting()34 virtual void OnReadWaiting() wxOVERRIDE 35 { 36 // Sync process, process all data coming at us from the pipe so that 37 // the pipe does not get full and cause a deadlock situation. 38 m_buf.Update(); 39 40 if ( m_buf.Eof() ) 41 DisableCallback(); 42 } 43 44 // These methods are never called as we only monitor the associated FD for 45 // reading, but we still must implement them as they're pure virtual in the 46 // base class. OnWriteWaiting()47 virtual void OnWriteWaiting() wxOVERRIDE { } OnExceptionWaiting()48 virtual void OnExceptionWaiting() wxOVERRIDE { } 49 50 // Disable any future calls to our OnReadWaiting(), can be called when 51 // we're sure that no more input is forthcoming. DisableCallback()52 void DisableCallback() 53 { 54 if ( !m_callbackDisabled ) 55 { 56 m_callbackDisabled = true; 57 58 DoDisable(); 59 } 60 } 61 62 protected: 63 const int m_fd; 64 65 private: 66 virtual void DoDisable() = 0; 67 68 wxStreamTempInputBuffer& m_buf; 69 70 // If true, DisableCallback() had been already called. 71 bool m_callbackDisabled; 72 73 wxDECLARE_NO_COPY_CLASS(wxExecuteIOHandlerBase); 74 }; 75 76 // This is the version used with wxFDIODispatcher, which must be passed to the 77 // ctor in order to register this handler with it. 78 class wxExecuteFDIOHandler : public wxExecuteIOHandlerBase<wxFDIOHandler> 79 { 80 public: wxExecuteFDIOHandler(wxFDIODispatcher & dispatcher,int fd,wxStreamTempInputBuffer & buf)81 wxExecuteFDIOHandler(wxFDIODispatcher& dispatcher, 82 int fd, 83 wxStreamTempInputBuffer& buf) 84 : wxExecuteIOHandlerBase<wxFDIOHandler>(fd, buf), 85 m_dispatcher(dispatcher) 86 { 87 dispatcher.RegisterFD(fd, this, wxFDIO_INPUT); 88 } 89 ~wxExecuteFDIOHandler()90 virtual ~wxExecuteFDIOHandler() 91 { 92 DisableCallback(); 93 } 94 95 private: DoDisable()96 virtual void DoDisable() wxOVERRIDE 97 { 98 m_dispatcher.UnregisterFD(m_fd); 99 } 100 101 wxFDIODispatcher& m_dispatcher; 102 103 wxDECLARE_NO_COPY_CLASS(wxExecuteFDIOHandler); 104 }; 105 106 // And this is the version used with an event loop. As AddSourceForFD() is 107 // static, we don't require passing the event loop to the ctor but an event 108 // loop must be running to handle our events. 109 class wxExecuteEventLoopSourceHandler 110 : public wxExecuteIOHandlerBase<wxEventLoopSourceHandler> 111 { 112 public: wxExecuteEventLoopSourceHandler(int fd,wxStreamTempInputBuffer & buf)113 wxExecuteEventLoopSourceHandler(int fd, wxStreamTempInputBuffer& buf) 114 : wxExecuteIOHandlerBase<wxEventLoopSourceHandler>(fd, buf) 115 { 116 m_source = wxEventLoop::AddSourceForFD(fd, this, wxEVENT_SOURCE_INPUT); 117 } 118 ~wxExecuteEventLoopSourceHandler()119 virtual ~wxExecuteEventLoopSourceHandler() 120 { 121 DisableCallback(); 122 } 123 124 private: DoDisable()125 virtual void DoDisable() wxOVERRIDE 126 { 127 delete m_source; 128 m_source = NULL; 129 } 130 131 wxEventLoopSource* m_source; 132 133 wxDECLARE_NO_COPY_CLASS(wxExecuteEventLoopSourceHandler); 134 }; 135 136 #endif // _WX_UNIX_PRIVATE_EXECUTEIOHANDLER_H_ 137