1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/evtloopunix.cpp
3 // Purpose: wxEventLoop implementation
4 // Author: Lukasz Michalski (lm@zork.pl)
6 // Copyright: (c) 2006 Zork Lukasz Michalski
7 // (c) 2009, 2013 Vadim Zeitlin <vadim@wxwidgets.org>
8 // (c) 2013 Rob Bresalier
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
23 #if wxUSE_CONSOLE_EVENTLOOP
25 #include "wx/evtloop.h"
32 #include "wx/apptrait.h"
33 #include "wx/scopedptr.h"
34 #include "wx/thread.h"
35 #include "wx/module.h"
36 #include "wx/unix/private/timer.h"
37 #include "wx/unix/private/epolldispatcher.h"
38 #include "wx/unix/private/wakeuppipe.h"
39 #include "wx/private/selectdispatcher.h"
40 #include "wx/private/eventloopsourcesmanager.h"
41 #include "wx/private/fdioeventloopsourcehandler.h"
42 #include "wx/private/eventloopsourcesmanager.h"
44 #if wxUSE_EVENTLOOP_SOURCE
45 #include "wx/evtloopsrc.h"
46 #endif // wxUSE_EVENTLOOP_SOURCE
48 // ===========================================================================
49 // wxEventLoop implementation
50 // ===========================================================================
52 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
56 wxConsoleEventLoop::wxConsoleEventLoop()
58 // Be pessimistic initially and assume that we failed to initialize.
61 m_wakeupSource
= NULL
;
64 wxScopedPtr
<wxWakeUpPipeMT
> wakeupPipe(new wxWakeUpPipeMT
);
65 const int pipeFD
= wakeupPipe
->GetReadFd();
66 if ( pipeFD
== wxPipe::INVALID_FD
)
69 // And start monitoring it in our event loop.
70 m_wakeupSource
= wxEventLoopBase::AddSourceForFD
77 if ( !m_wakeupSource
)
80 // This is a bit ugly but we know that AddSourceForFD() used the currently
81 // active dispatcher to register this source, so use the same one for our
82 // other operations. Of course, currently the dispatcher returned by
83 // wxFDIODispatcher::Get() is always the same one anyhow so it doesn't
84 // really matter, but if we started returning different things later, it
86 m_dispatcher
= wxFDIODispatcher::Get();
88 m_wakeupPipe
= wakeupPipe
.release();
91 wxConsoleEventLoop::~wxConsoleEventLoop()
95 delete m_wakeupSource
;
101 //-----------------------------------------------------------------------------
102 // adding & removing sources
103 //-----------------------------------------------------------------------------
105 #if wxUSE_EVENTLOOP_SOURCE
107 class wxConsoleEventLoopSourcesManager
: public wxEventLoopSourcesManagerBase
110 wxEventLoopSource
* AddSourceForFD( int fd
,
111 wxEventLoopSourceHandler
*handler
,
114 wxCHECK_MSG( fd
!= -1, NULL
, "can't monitor invalid fd" );
116 wxLogTrace(wxTRACE_EVT_SOURCE
,
117 "Adding event loop source for fd=%d", fd
);
119 // we need a bridge to wxFDIODispatcher
121 // TODO: refactor the code so that only wxEventLoopSourceHandler is used
122 wxScopedPtr
<wxFDIOHandler
>
123 fdioHandler(new wxFDIOEventLoopSourceHandler(handler
));
125 if ( !wxFDIODispatcher::Get()->RegisterFD(fd
, fdioHandler
.get(), flags
) )
128 return new wxUnixEventLoopSource(wxFDIODispatcher::Get(), fdioHandler
.release(),
133 wxEventLoopSourcesManagerBase
* wxAppTraits::GetEventLoopSourcesManager()
135 static wxConsoleEventLoopSourcesManager s_eventLoopSourcesManager
;
137 return &s_eventLoopSourcesManager
;
140 wxUnixEventLoopSource::~wxUnixEventLoopSource()
142 wxLogTrace(wxTRACE_EVT_SOURCE
,
143 "Removing event loop source for fd=%d", m_fd
);
145 m_dispatcher
->UnregisterFD(m_fd
);
147 delete m_fdioHandler
;
150 #endif // wxUSE_EVENTLOOP_SOURCE
152 //-----------------------------------------------------------------------------
153 // events dispatch and loop handling
154 //-----------------------------------------------------------------------------
156 bool wxConsoleEventLoop::Pending() const
158 if ( m_dispatcher
->HasPending() )
162 wxUsecClock_t nextTimer
;
163 if ( wxTimerScheduler::Get().GetNext(&nextTimer
) &&
164 !wxMilliClockToLong(nextTimer
) )
166 #endif // wxUSE_TIMER
171 bool wxConsoleEventLoop::Dispatch()
173 DispatchTimeout(static_cast<unsigned long>(
174 wxFDIODispatcher::TIMEOUT_INFINITE
));
179 int wxConsoleEventLoop::DispatchTimeout(unsigned long timeout
)
182 // check if we need to decrease the timeout to account for a timer
183 wxUsecClock_t nextTimer
;
184 if ( wxTimerScheduler::Get().GetNext(&nextTimer
) )
186 unsigned long timeUntilNextTimer
= wxMilliClockToLong(nextTimer
/ 1000);
187 if ( timeUntilNextTimer
< timeout
)
188 timeout
= timeUntilNextTimer
;
190 #endif // wxUSE_TIMER
192 bool hadEvent
= m_dispatcher
->Dispatch(timeout
) > 0;
195 if ( wxTimerScheduler::Get().NotifyExpired() )
197 #endif // wxUSE_TIMER
199 return hadEvent
? 1 : -1;
202 void wxConsoleEventLoop::WakeUp()
204 m_wakeupPipe
->WakeUp();
207 void wxConsoleEventLoop::OnNextIteration()
209 // call the signal handlers for any signals we caught recently
210 wxTheApp
->CheckSignal();
214 wxEventLoopBase
*wxConsoleAppTraits::CreateEventLoop()
216 return new wxEventLoop();
219 #endif // wxUSE_CONSOLE_EVENTLOOP