1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/evtloopunix.cpp
3 // Purpose: wxEventLoop implementation
4 // Author: Lukasz Michalski (lm@zork.pl)
7 // Copyright: (c) 2006 Zork Lukasz Michalski
8 // (c) 2009, 2013 Vadim Zeitlin <vadim@wxwidgets.org>
9 // (c) 2013 Rob Bresalier
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
13 // ===========================================================================
15 // ===========================================================================
17 // ---------------------------------------------------------------------------
19 // ---------------------------------------------------------------------------
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
24 #if wxUSE_CONSOLE_EVENTLOOP
26 #include "wx/evtloop.h"
33 #include "wx/apptrait.h"
34 #include "wx/scopedptr.h"
35 #include "wx/thread.h"
36 #include "wx/module.h"
37 #include "wx/unix/private/timer.h"
38 #include "wx/unix/private/epolldispatcher.h"
39 #include "wx/unix/private/wakeuppipe.h"
40 #include "wx/private/selectdispatcher.h"
41 #include "wx/private/eventloopsourcesmanager.h"
42 #include "wx/private/fdioeventloopsourcehandler.h"
43 #include "wx/private/eventloopsourcesmanager.h"
45 #if wxUSE_EVENTLOOP_SOURCE
46 #include "wx/evtloopsrc.h"
47 #endif // wxUSE_EVENTLOOP_SOURCE
49 // ===========================================================================
50 // wxEventLoop implementation
51 // ===========================================================================
53 //-----------------------------------------------------------------------------
55 //-----------------------------------------------------------------------------
57 wxConsoleEventLoop::wxConsoleEventLoop()
59 // Be pessimistic initially and assume that we failed to initialize.
62 m_wakeupSource
= NULL
;
65 wxScopedPtr
<wxWakeUpPipeMT
> wakeupPipe(new wxWakeUpPipeMT
);
66 const int pipeFD
= wakeupPipe
->GetReadFd();
67 if ( pipeFD
== wxPipe::INVALID_FD
)
70 // And start monitoring it in our event loop.
71 m_wakeupSource
= wxEventLoopBase::AddSourceForFD
78 if ( !m_wakeupSource
)
81 // This is a bit ugly but we know that AddSourceForFD() used the currently
82 // active dispatcher to register this source, so use the same one for our
83 // other operations. Of course, currently the dispatcher returned by
84 // wxFDIODispatcher::Get() is always the same one anyhow so it doesn't
85 // really matter, but if we started returning different things later, it
87 m_dispatcher
= wxFDIODispatcher::Get();
89 m_wakeupPipe
= wakeupPipe
.release();
92 wxConsoleEventLoop::~wxConsoleEventLoop()
96 delete m_wakeupSource
;
102 //-----------------------------------------------------------------------------
103 // adding & removing sources
104 //-----------------------------------------------------------------------------
106 #if wxUSE_EVENTLOOP_SOURCE
108 class wxConsoleEventLoopSourcesManager
: public wxEventLoopSourcesManagerBase
111 wxEventLoopSource
* AddSourceForFD( int fd
,
112 wxEventLoopSourceHandler
*handler
,
115 wxCHECK_MSG( fd
!= -1, NULL
, "can't monitor invalid fd" );
117 wxLogTrace(wxTRACE_EVT_SOURCE
,
118 "Adding event loop source for fd=%d", fd
);
120 // we need a bridge to wxFDIODispatcher
122 // TODO: refactor the code so that only wxEventLoopSourceHandler is used
123 wxScopedPtr
<wxFDIOHandler
>
124 fdioHandler(new wxFDIOEventLoopSourceHandler(handler
));
126 if ( !wxFDIODispatcher::Get()->RegisterFD(fd
, fdioHandler
.get(), flags
) )
129 return new wxUnixEventLoopSource(wxFDIODispatcher::Get(), fdioHandler
.release(),
134 wxEventLoopSourcesManagerBase
* wxAppTraits::GetEventLoopSourcesManager()
136 static wxConsoleEventLoopSourcesManager s_eventLoopSourcesManager
;
138 return &s_eventLoopSourcesManager
;
141 wxUnixEventLoopSource::~wxUnixEventLoopSource()
143 wxLogTrace(wxTRACE_EVT_SOURCE
,
144 "Removing event loop source for fd=%d", m_fd
);
146 m_dispatcher
->UnregisterFD(m_fd
);
148 delete m_fdioHandler
;
151 #endif // wxUSE_EVENTLOOP_SOURCE
153 //-----------------------------------------------------------------------------
154 // events dispatch and loop handling
155 //-----------------------------------------------------------------------------
157 bool wxConsoleEventLoop::Pending() const
159 if ( m_dispatcher
->HasPending() )
163 wxUsecClock_t nextTimer
;
164 if ( wxTimerScheduler::Get().GetNext(&nextTimer
) &&
165 !wxMilliClockToLong(nextTimer
) )
167 #endif // wxUSE_TIMER
172 bool wxConsoleEventLoop::Dispatch()
174 DispatchTimeout(static_cast<unsigned long>(
175 wxFDIODispatcher::TIMEOUT_INFINITE
));
180 int wxConsoleEventLoop::DispatchTimeout(unsigned long timeout
)
183 // check if we need to decrease the timeout to account for a timer
184 wxUsecClock_t nextTimer
;
185 if ( wxTimerScheduler::Get().GetNext(&nextTimer
) )
187 unsigned long timeUntilNextTimer
= wxMilliClockToLong(nextTimer
/ 1000);
188 if ( timeUntilNextTimer
< timeout
)
189 timeout
= timeUntilNextTimer
;
191 #endif // wxUSE_TIMER
193 bool hadEvent
= m_dispatcher
->Dispatch(timeout
) > 0;
196 if ( wxTimerScheduler::Get().NotifyExpired() )
198 #endif // wxUSE_TIMER
200 return hadEvent
? 1 : -1;
203 void wxConsoleEventLoop::WakeUp()
205 m_wakeupPipe
->WakeUp();
208 void wxConsoleEventLoop::OnNextIteration()
210 // call the signal handlers for any signals we caught recently
211 wxTheApp
->CheckSignal();
215 wxEventLoopBase
*wxConsoleAppTraits::CreateEventLoop()
217 return new wxEventLoop();
220 #endif // wxUSE_CONSOLE_EVENTLOOP