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 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // ===========================================================================
13 // ===========================================================================
15 // ---------------------------------------------------------------------------
17 // ---------------------------------------------------------------------------
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
22 #if wxUSE_CONSOLE_EVENTLOOP
24 #include "wx/evtloop.h"
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"
43 #if wxUSE_EVENTLOOP_SOURCE
44 #include "wx/evtloopsrc.h"
45 #endif // wxUSE_EVENTLOOP_SOURCE
47 // ===========================================================================
48 // wxEventLoop implementation
49 // ===========================================================================
51 //-----------------------------------------------------------------------------
53 //-----------------------------------------------------------------------------
55 wxConsoleEventLoop::wxConsoleEventLoop()
57 // Be pessimistic initially and assume that we failed to initialize.
60 m_wakeupSource
= NULL
;
63 wxScopedPtr
<wxWakeUpPipeMT
> wakeupPipe(new wxWakeUpPipeMT
);
64 const int pipeFD
= wakeupPipe
->GetReadFd();
65 if ( pipeFD
== wxPipe::INVALID_FD
)
68 // And start monitoring it in our event loop.
69 m_wakeupSource
= wxEventLoopBase::AddSourceForFD
76 if ( !m_wakeupSource
)
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
85 m_dispatcher
= wxFDIODispatcher::Get();
87 m_wakeupPipe
= wakeupPipe
.release();
90 wxConsoleEventLoop::~wxConsoleEventLoop()
94 delete m_wakeupSource
;
100 //-----------------------------------------------------------------------------
101 // adding & removing sources
102 //-----------------------------------------------------------------------------
104 #if wxUSE_EVENTLOOP_SOURCE
106 class wxConsoleEventLoopSourcesManager
: public wxEventLoopSourcesManagerBase
109 wxEventLoopSource
* AddSourceForFD( int fd
,
110 wxEventLoopSourceHandler
*handler
,
113 wxCHECK_MSG( fd
!= -1, NULL
, "can't monitor invalid fd" );
115 wxLogTrace(wxTRACE_EVT_SOURCE
,
116 "Adding event loop source for fd=%d", fd
);
118 // we need a bridge to wxFDIODispatcher
120 // TODO: refactor the code so that only wxEventLoopSourceHandler is used
121 wxScopedPtr
<wxFDIOHandler
>
122 fdioHandler(new wxFDIOEventLoopSourceHandler(handler
));
124 if ( !wxFDIODispatcher::Get()->RegisterFD(fd
, fdioHandler
.get(), flags
) )
127 return new wxUnixEventLoopSource(wxFDIODispatcher::Get(), fdioHandler
.release(),
132 wxEventLoopSourcesManagerBase
* wxAppTraits::GetEventLoopSourcesManager()
134 static wxConsoleEventLoopSourcesManager s_eventLoopSourcesManager
;
136 return &s_eventLoopSourcesManager
;
139 wxUnixEventLoopSource::~wxUnixEventLoopSource()
141 wxLogTrace(wxTRACE_EVT_SOURCE
,
142 "Removing event loop source for fd=%d", m_fd
);
144 m_dispatcher
->UnregisterFD(m_fd
);
146 delete m_fdioHandler
;
149 #endif // wxUSE_EVENTLOOP_SOURCE
151 //-----------------------------------------------------------------------------
152 // events dispatch and loop handling
153 //-----------------------------------------------------------------------------
155 bool wxConsoleEventLoop::Pending() const
157 if ( m_dispatcher
->HasPending() )
161 wxUsecClock_t nextTimer
;
162 if ( wxTimerScheduler::Get().GetNext(&nextTimer
) &&
163 !wxMilliClockToLong(nextTimer
) )
165 #endif // wxUSE_TIMER
170 bool wxConsoleEventLoop::Dispatch()
172 DispatchTimeout(static_cast<unsigned long>(
173 wxFDIODispatcher::TIMEOUT_INFINITE
));
178 int wxConsoleEventLoop::DispatchTimeout(unsigned long timeout
)
181 // check if we need to decrease the timeout to account for a timer
182 wxUsecClock_t nextTimer
;
183 if ( wxTimerScheduler::Get().GetNext(&nextTimer
) )
185 unsigned long timeUntilNextTimer
= wxMilliClockToLong(nextTimer
/ 1000);
186 if ( timeUntilNextTimer
< timeout
)
187 timeout
= timeUntilNextTimer
;
189 #endif // wxUSE_TIMER
191 bool hadEvent
= m_dispatcher
->Dispatch(timeout
) > 0;
194 if ( wxTimerScheduler::Get().NotifyExpired() )
196 #endif // wxUSE_TIMER
198 return hadEvent
? 1 : -1;
201 void wxConsoleEventLoop::WakeUp()
203 m_wakeupPipe
->WakeUp();
206 void wxConsoleEventLoop::OnNextIteration()
208 // call the signal handlers for any signals we caught recently
209 wxTheApp
->CheckSignal();
213 wxEventLoopBase
*wxConsoleAppTraits::CreateEventLoop()
215 return new wxEventLoop();
218 #endif // wxUSE_CONSOLE_EVENTLOOP