]>
git.saurik.com Git - wxWidgets.git/blob - src/unix/evtloopunix.cpp
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
30 #include "wx/apptrait.h"
31 #include "wx/evtloop.h"
32 #include "wx/thread.h"
33 #include "wx/module.h"
34 #include "wx/unix/pipe.h"
35 #include "wx/unix/private/timer.h"
36 #include "wx/unix/private/epolldispatcher.h"
37 #include "wx/private/selectdispatcher.h"
39 #define TRACE_EVENTS _T("events")
41 // ===========================================================================
42 // wxEventLoop::PipeIOHandler implementation
43 // ===========================================================================
48 // pipe used for wake up messages: when a child thread wants to wake up
49 // the event loop in the main thread it writes to this pipe
50 class PipeIOHandler
: public wxFDIOHandler
53 // default ctor does nothing, call Create() to really initialize the
59 // this method can be, and normally is, called from another thread
62 int GetReadFd() { return m_pipe
[wxPipe::Read
]; }
64 // implement wxFDIOHandler pure virtual methods
65 virtual void OnReadWaiting();
66 virtual void OnWriteWaiting() { }
67 virtual void OnExceptionWaiting() { }
73 // ----------------------------------------------------------------------------
75 // ----------------------------------------------------------------------------
77 bool PipeIOHandler::Create()
79 if ( !m_pipe
.Create() )
81 wxLogError(_("Failed to create wake up pipe used by event loop."));
85 const int fdRead
= GetReadFd();
87 int flags
= fcntl(fdRead
, F_GETFL
, 0);
88 if ( flags
== -1 || fcntl(fdRead
, F_SETFL
, flags
| O_NONBLOCK
) == -1 )
90 wxLogSysError(_("Failed to switch wake up pipe to non-blocking mode"));
94 wxLogTrace(TRACE_EVENTS
, wxT("Wake up pipe (%d, %d) created"),
95 fdRead
, m_pipe
[wxPipe::Write
]);
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
104 void PipeIOHandler::WakeUp()
106 if ( write(m_pipe
[wxPipe::Write
], "s", 1) != 1 )
108 // don't use wxLog here, we can be in another thread and this could
109 // result in dead locks
110 perror("write(wake up pipe)");
114 void PipeIOHandler::OnReadWaiting()
116 // got wakeup from child thread: read all data available in pipe just to
117 // make it empty (even though we write one byte at a time from WakeUp(),
118 // it could have been called several times)
122 const int size
= read(GetReadFd(), buf
, WXSIZEOF(buf
));
124 if ( size
== 0 || (size
== -1 && (errno
== EAGAIN
|| errno
== EINTR
)) )
126 // nothing left in the pipe (EAGAIN is expected for an FD with
133 wxLogSysError(_("Failed to read from wake-up pipe"));
139 // writing to the wake up pipe will make wxConsoleEventLoop return from
140 // wxFDIODispatcher::Dispatch() it might be currently blocking in, nothing
141 // else needs to be done
144 } // namespace wxPrivate
146 // ===========================================================================
147 // wxEventLoop implementation
148 // ===========================================================================
150 //-----------------------------------------------------------------------------
152 //-----------------------------------------------------------------------------
154 wxConsoleEventLoop::wxConsoleEventLoop()
156 m_wakeupPipe
= new wxPrivate::PipeIOHandler();
157 if ( !m_wakeupPipe
->Create() )
159 wxDELETE(m_wakeupPipe
);
164 m_dispatcher
= wxFDIODispatcher::Get();
168 m_dispatcher
->RegisterFD
170 m_wakeupPipe
->GetReadFd(),
176 wxConsoleEventLoop::~wxConsoleEventLoop()
181 //-----------------------------------------------------------------------------
182 // events dispatch and loop handling
183 //-----------------------------------------------------------------------------
185 bool wxConsoleEventLoop::Pending() const
187 if ( m_dispatcher
->HasPending() )
191 wxUsecClock_t nextTimer
;
192 if ( wxTimerScheduler::Get().GetNext(&nextTimer
) &&
193 !wxMilliClockToLong(nextTimer
) )
195 #endif // wxUSE_TIMER
200 bool wxConsoleEventLoop::Dispatch()
202 DispatchTimeout(wxFDIODispatcher::TIMEOUT_INFINITE
);
207 int wxConsoleEventLoop::DispatchTimeout(unsigned long timeout
)
210 // check if we need to decrease the timeout to account for a timer
211 wxUsecClock_t nextTimer
;
212 if ( wxTimerScheduler::Get().GetNext(&nextTimer
) )
214 unsigned long timeUntilNextTimer
= wxMilliClockToLong(nextTimer
/ 1000);
215 if ( timeUntilNextTimer
< timeout
)
216 timeout
= timeUntilNextTimer
;
218 #endif // wxUSE_TIMER
220 bool hadEvent
= m_dispatcher
->Dispatch(timeout
) > 0;
223 if ( wxTimerScheduler::Get().NotifyExpired() )
225 #endif // wxUSE_TIMER
227 return hadEvent
? 1 : -1;
230 void wxConsoleEventLoop::WakeUp()
232 m_wakeupPipe
->WakeUp();
235 void wxConsoleEventLoop::OnNextIteration()
237 // call the signal handlers for any signals we caught recently
238 wxTheApp
->CheckSignal();
242 wxEventLoopBase
*wxConsoleAppTraits::CreateEventLoop()
244 return new wxEventLoop();
247 #endif // wxUSE_CONSOLE_EVENTLOOP