Extract PipeIOHandler class into a header and rename to wxWakeUpPipe.
[wxWidgets.git] / src / unix / evtloopunix.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/evtloopunix.cpp
3 // Purpose: wxEventLoop implementation
4 // Author: Lukasz Michalski (lm@zork.pl)
5 // Created: 2007-05-07
6 // RCS-ID: $Id$
7 // Copyright: (c) 2006 Zork Lukasz Michalski
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ===========================================================================
12 // declarations
13 // ===========================================================================
14
15 // ---------------------------------------------------------------------------
16 // headers
17 // ---------------------------------------------------------------------------
18
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #if wxUSE_CONSOLE_EVENTLOOP
23
24 #include "wx/evtloop.h"
25
26 #ifndef WX_PRECOMP
27 #include "wx/app.h"
28 #include "wx/log.h"
29 #endif
30
31 #include "wx/apptrait.h"
32 #include "wx/scopedptr.h"
33 #include "wx/thread.h"
34 #include "wx/module.h"
35 #include "wx/unix/private/timer.h"
36 #include "wx/unix/private/epolldispatcher.h"
37 #include "wx/unix/private/wakeuppipe.h"
38 #include "wx/private/selectdispatcher.h"
39
40 #if wxUSE_EVENTLOOP_SOURCE
41 #include "wx/evtloopsrc.h"
42 #endif // wxUSE_EVENTLOOP_SOURCE
43
44 // ===========================================================================
45 // wxEventLoop implementation
46 // ===========================================================================
47
48 //-----------------------------------------------------------------------------
49 // initialization
50 //-----------------------------------------------------------------------------
51
52 wxConsoleEventLoop::wxConsoleEventLoop()
53 {
54 m_wakeupPipe = new wxWakeUpPipe;
55 const int pipeFD = m_wakeupPipe->GetReadFd();
56 if ( pipeFD == wxPipe::INVALID_FD )
57 {
58 wxDELETE(m_wakeupPipe);
59 m_dispatcher = NULL;
60 return;
61 }
62
63 m_dispatcher = wxFDIODispatcher::Get();
64 if ( !m_dispatcher )
65 return;
66
67 m_dispatcher->RegisterFD(pipeFD, m_wakeupPipe, wxFDIO_INPUT);
68 }
69
70 wxConsoleEventLoop::~wxConsoleEventLoop()
71 {
72 if ( m_wakeupPipe )
73 {
74 if ( m_dispatcher )
75 {
76 m_dispatcher->UnregisterFD(m_wakeupPipe->GetReadFd());
77 }
78
79 delete m_wakeupPipe;
80 }
81 }
82
83 //-----------------------------------------------------------------------------
84 // adding & removing sources
85 //-----------------------------------------------------------------------------
86
87 #if wxUSE_EVENTLOOP_SOURCE
88
89 // This class is a temporary bridge between event loop sources and
90 // FDIODispatcher. It is going to be removed soon, when all subject interfaces
91 // are modified
92 class wxFDIOEventLoopSourceHandler : public wxFDIOHandler
93 {
94 public:
95 wxFDIOEventLoopSourceHandler(wxEventLoopSourceHandler* handler) :
96 m_impl(handler) { }
97
98 virtual void OnReadWaiting()
99 {
100 m_impl->OnReadWaiting();
101 }
102 virtual void OnWriteWaiting()
103 {
104 m_impl->OnWriteWaiting();
105 }
106
107 virtual void OnExceptionWaiting()
108 {
109 m_impl->OnExceptionWaiting();
110 }
111
112 protected:
113 wxEventLoopSourceHandler* m_impl;
114 };
115
116 wxEventLoopSource *
117 wxConsoleEventLoop::AddSourceForFD(int fd,
118 wxEventLoopSourceHandler *handler,
119 int flags)
120 {
121 wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" );
122
123 wxLogTrace(wxTRACE_EVT_SOURCE,
124 "Adding event loop source for fd=%d", fd);
125
126 // we need a bridge to wxFDIODispatcher
127 //
128 // TODO: refactor the code so that only wxEventLoopSourceHandler is used
129 wxScopedPtr<wxFDIOHandler>
130 fdioHandler(new wxFDIOEventLoopSourceHandler(handler));
131
132 if ( !m_dispatcher->RegisterFD(fd, fdioHandler.get(), flags) )
133 return NULL;
134
135 return new wxUnixEventLoopSource(m_dispatcher, fdioHandler.release(),
136 fd, handler, flags);
137 }
138
139 wxUnixEventLoopSource::~wxUnixEventLoopSource()
140 {
141 wxLogTrace(wxTRACE_EVT_SOURCE,
142 "Removing event loop source for fd=%d", m_fd);
143
144 m_dispatcher->UnregisterFD(m_fd);
145
146 delete m_fdioHandler;
147 }
148
149 #endif // wxUSE_EVENTLOOP_SOURCE
150
151 //-----------------------------------------------------------------------------
152 // events dispatch and loop handling
153 //-----------------------------------------------------------------------------
154
155 bool wxConsoleEventLoop::Pending() const
156 {
157 if ( m_dispatcher->HasPending() )
158 return true;
159
160 #if wxUSE_TIMER
161 wxUsecClock_t nextTimer;
162 if ( wxTimerScheduler::Get().GetNext(&nextTimer) &&
163 !wxMilliClockToLong(nextTimer) )
164 return true;
165 #endif // wxUSE_TIMER
166
167 return false;
168 }
169
170 bool wxConsoleEventLoop::Dispatch()
171 {
172 DispatchTimeout(static_cast<unsigned long>(
173 wxFDIODispatcher::TIMEOUT_INFINITE));
174
175 return true;
176 }
177
178 int wxConsoleEventLoop::DispatchTimeout(unsigned long timeout)
179 {
180 #if wxUSE_TIMER
181 // check if we need to decrease the timeout to account for a timer
182 wxUsecClock_t nextTimer;
183 if ( wxTimerScheduler::Get().GetNext(&nextTimer) )
184 {
185 unsigned long timeUntilNextTimer = wxMilliClockToLong(nextTimer / 1000);
186 if ( timeUntilNextTimer < timeout )
187 timeout = timeUntilNextTimer;
188 }
189 #endif // wxUSE_TIMER
190
191 bool hadEvent = m_dispatcher->Dispatch(timeout) > 0;
192
193 #if wxUSE_TIMER
194 if ( wxTimerScheduler::Get().NotifyExpired() )
195 hadEvent = true;
196 #endif // wxUSE_TIMER
197
198 return hadEvent ? 1 : -1;
199 }
200
201 void wxConsoleEventLoop::WakeUp()
202 {
203 m_wakeupPipe->WakeUp();
204 }
205
206 void wxConsoleEventLoop::OnNextIteration()
207 {
208 // call the signal handlers for any signals we caught recently
209 wxTheApp->CheckSignal();
210 }
211
212
213 wxEventLoopBase *wxConsoleAppTraits::CreateEventLoop()
214 {
215 return new wxEventLoop();
216 }
217
218 #endif // wxUSE_CONSOLE_EVENTLOOP