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