X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9af42efda6c78093872a67180d43d5eeba261fee..ba86da30cf1a2a8429f3af465cbb6c9f52b307fb:/src/unix/evtloopunix.cpp diff --git a/src/unix/evtloopunix.cpp b/src/unix/evtloopunix.cpp index 7f27c1c2a2..4edf70e696 100644 --- a/src/unix/evtloopunix.cpp +++ b/src/unix/evtloopunix.cpp @@ -21,6 +21,8 @@ #if wxUSE_CONSOLE_EVENTLOOP +#include "wx/evtloop.h" + #ifndef WX_PRECOMP #include "wx/app.h" #include "wx/log.h" @@ -28,9 +30,9 @@ #include #include "wx/apptrait.h" -#include "wx/evtloop.h" #include "wx/thread.h" #include "wx/module.h" +#include "wx/unix/pipe.h" #include "wx/unix/private/timer.h" #include "wx/unix/private/epolldispatcher.h" #include "wx/private/selectdispatcher.h" @@ -41,11 +43,39 @@ // wxEventLoop::PipeIOHandler implementation // =========================================================================== +namespace wxPrivate +{ + +// pipe used for wake up messages: when a child thread wants to wake up +// the event loop in the main thread it writes to this pipe +class PipeIOHandler : public wxFDIOHandler +{ +public: + // default ctor does nothing, call Create() to really initialize the + // object + PipeIOHandler() { } + + bool Create(); + + // this method can be, and normally is, called from another thread + void WakeUp(); + + int GetReadFd() { return m_pipe[wxPipe::Read]; } + + // implement wxFDIOHandler pure virtual methods + virtual void OnReadWaiting(); + virtual void OnWriteWaiting() { } + virtual void OnExceptionWaiting() { } + +private: + wxPipe m_pipe; +}; + // ---------------------------------------------------------------------------- // initialization // ---------------------------------------------------------------------------- -bool wxConsoleEventLoop::PipeIOHandler::Create() +bool PipeIOHandler::Create() { if ( !m_pipe.Create() ) { @@ -72,7 +102,7 @@ bool wxConsoleEventLoop::PipeIOHandler::Create() // wakeup handling // ---------------------------------------------------------------------------- -void wxConsoleEventLoop::PipeIOHandler::WakeUp() +void PipeIOHandler::WakeUp() { if ( write(m_pipe[wxPipe::Write], "s", 1) != 1 ) { @@ -82,17 +112,17 @@ void wxConsoleEventLoop::PipeIOHandler::WakeUp() } } -void wxConsoleEventLoop::PipeIOHandler::OnReadWaiting() +void PipeIOHandler::OnReadWaiting() { // got wakeup from child thread: read all data available in pipe just to - // make it empty (evevn though we write one byte at a time from WakeUp(), + // make it empty (even though we write one byte at a time from WakeUp(), // it could have been called several times) char buf[4]; for ( ;; ) { const int size = read(GetReadFd(), buf, WXSIZEOF(buf)); - if ( size == 0 || (size == -1 && errno == EAGAIN) ) + if ( size == 0 || (size == -1 && (errno == EAGAIN || errno == EINTR)) ) { // nothing left in the pipe (EAGAIN is expected for an FD with // O_NONBLOCK) @@ -107,9 +137,13 @@ void wxConsoleEventLoop::PipeIOHandler::OnReadWaiting() } } - wxTheApp->ProcessPendingEvents(); + // writing to the wake up pipe will make wxConsoleEventLoop return from + // wxFDIODispatcher::Dispatch() it might be currently blocking in, nothing + // else needs to be done } +} // namespace wxPrivate + // =========================================================================== // wxEventLoop implementation // =========================================================================== @@ -120,8 +154,10 @@ void wxConsoleEventLoop::PipeIOHandler::OnReadWaiting() wxConsoleEventLoop::wxConsoleEventLoop() { - if ( !m_wakeupPipe.Create() ) + m_wakeupPipe = new wxPrivate::PipeIOHandler(); + if ( !m_wakeupPipe->Create() ) { + wxDELETE(m_wakeupPipe); m_dispatcher = NULL; return; } @@ -132,19 +168,34 @@ wxConsoleEventLoop::wxConsoleEventLoop() m_dispatcher->RegisterFD ( - m_wakeupPipe.GetReadFd(), - &m_wakeupPipe, + m_wakeupPipe->GetReadFd(), + m_wakeupPipe, wxFDIO_INPUT ); } +wxConsoleEventLoop::~wxConsoleEventLoop() +{ + delete m_wakeupPipe; +} + //----------------------------------------------------------------------------- // events dispatch and loop handling //----------------------------------------------------------------------------- bool wxConsoleEventLoop::Pending() const { - return wxTheApp->HasPendingEvents(); + if ( m_dispatcher->HasPending() ) + return true; + +#if wxUSE_TIMER + wxUsecClock_t nextTimer; + if ( wxTimerScheduler::Get().GetNext(&nextTimer) && + !wxMilliClockToLong(nextTimer) ) + return true; +#endif // wxUSE_TIMER + + return false; } bool wxConsoleEventLoop::Dispatch() @@ -167,21 +218,19 @@ int wxConsoleEventLoop::DispatchTimeout(unsigned long timeout) } #endif // wxUSE_TIMER - bool hadEvent = m_dispatcher->Dispatch(timeout); + bool hadEvent = m_dispatcher->Dispatch(timeout) > 0; #if wxUSE_TIMER if ( wxTimerScheduler::Get().NotifyExpired() ) hadEvent = true; #endif // wxUSE_TIMER - wxTheApp->ProcessPendingEvents(); - return hadEvent ? 1 : -1; } void wxConsoleEventLoop::WakeUp() { - m_wakeupPipe.WakeUp(); + m_wakeupPipe->WakeUp(); } void wxConsoleEventLoop::OnNextIteration()