Change wxWakeUpPipe to be a wxEventLoopSourceHandler.
[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 #include "wx/private/eventloopsourcesmanager.h"
40 #include "wx/private/fdioeventloopsourcehandler.h"
41 #include "wx/private/eventloopsourcesmanager.h"
42
43 #if wxUSE_EVENTLOOP_SOURCE
44 #include "wx/evtloopsrc.h"
45 #endif // wxUSE_EVENTLOOP_SOURCE
46
47 // ===========================================================================
48 // wxEventLoop implementation
49 // ===========================================================================
50
51 //-----------------------------------------------------------------------------
52 // initialization
53 //-----------------------------------------------------------------------------
54
55 wxConsoleEventLoop::wxConsoleEventLoop()
56 {
57 // Be pessimistic initially and assume that we failed to initialize.
58 m_dispatcher = NULL;
59 m_wakeupPipe = NULL;
60 m_wakeupSource = NULL;
61
62 // Create the pipe.
63 wxScopedPtr<wxWakeUpPipeMT> wakeupPipe(new wxWakeUpPipeMT);
64 const int pipeFD = wakeupPipe->GetReadFd();
65 if ( pipeFD == wxPipe::INVALID_FD )
66 return;
67
68 // And start monitoring it in our event loop.
69 m_wakeupSource = wxEventLoopBase::AddSourceForFD
70 (
71 pipeFD,
72 wakeupPipe.get(),
73 wxFDIO_INPUT
74 );
75
76 if ( !m_wakeupSource )
77 return;
78
79 // This is a bit ugly but we know that AddSourceForFD() used the currently
80 // active dispatcher to register this source, so use the same one for our
81 // other operations. Of course, currently the dispatcher returned by
82 // wxFDIODispatcher::Get() is always the same one anyhow so it doesn't
83 // really matter, but if we started returning different things later, it
84 // would.
85 m_dispatcher = wxFDIODispatcher::Get();
86
87 m_wakeupPipe = wakeupPipe.release();
88 }
89
90 wxConsoleEventLoop::~wxConsoleEventLoop()
91 {
92 if ( m_wakeupPipe )
93 {
94 delete m_wakeupSource;
95
96 delete m_wakeupPipe;
97 }
98 }
99
100 //-----------------------------------------------------------------------------
101 // adding & removing sources
102 //-----------------------------------------------------------------------------
103
104 #if wxUSE_EVENTLOOP_SOURCE
105
106 class wxConsoleEventLoopSourcesManager : public wxEventLoopSourcesManagerBase
107 {
108 public:
109 wxEventLoopSource* AddSourceForFD( int fd,
110 wxEventLoopSourceHandler *handler,
111 int flags)
112 {
113 wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" );
114
115 wxLogTrace(wxTRACE_EVT_SOURCE,
116 "Adding event loop source for fd=%d", fd);
117
118 // we need a bridge to wxFDIODispatcher
119 //
120 // TODO: refactor the code so that only wxEventLoopSourceHandler is used
121 wxScopedPtr<wxFDIOHandler>
122 fdioHandler(new wxFDIOEventLoopSourceHandler(handler));
123
124 if ( !wxFDIODispatcher::Get()->RegisterFD(fd, fdioHandler.get(), flags) )
125 return NULL;
126
127 return new wxUnixEventLoopSource(wxFDIODispatcher::Get(), fdioHandler.release(),
128 fd, handler, flags);
129 }
130 };
131
132 wxEventLoopSourcesManagerBase* wxAppTraits::GetEventLoopSourcesManager()
133 {
134 static wxConsoleEventLoopSourcesManager s_eventLoopSourcesManager;
135
136 return &s_eventLoopSourcesManager;
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