X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c22ace4dff0629aa55f5afb9fa7d77334d27409b..a25b76f5f92c3cc116cb4ca53e8e5a6bcd3ff42f:/src/unix/evtloopunix.cpp diff --git a/src/unix/evtloopunix.cpp b/src/unix/evtloopunix.cpp index 5797b5eedb..763b73ef73 100644 --- a/src/unix/evtloopunix.cpp +++ b/src/unix/evtloopunix.cpp @@ -28,157 +28,112 @@ #include "wx/log.h" #endif -#include #include "wx/apptrait.h" +#include "wx/scopedptr.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/unix/private/wakeuppipe.h" #include "wx/private/selectdispatcher.h" +#include "wx/private/eventloopsourcesmanager.h" +#include "wx/private/fdioeventloopsourcehandler.h" +#include "wx/private/eventloopsourcesmanager.h" -#define TRACE_EVENTS _T("events") +#if wxUSE_EVENTLOOP_SOURCE + #include "wx/evtloopsrc.h" +#endif // wxUSE_EVENTLOOP_SOURCE // =========================================================================== -// wxEventLoop::PipeIOHandler implementation +// wxEventLoop 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 PipeIOHandler::Create() +wxConsoleEventLoop::wxConsoleEventLoop() { - if ( !m_pipe.Create() ) - { - wxLogError(_("Failed to create wake up pipe used by event loop.")); - return false; - } - - const int fdRead = GetReadFd(); - - int flags = fcntl(fdRead, F_GETFL, 0); - if ( flags == -1 || fcntl(fdRead, F_SETFL, flags | O_NONBLOCK) == -1 ) + m_wakeupPipe = new wxWakeUpPipeMT; + const int pipeFD = m_wakeupPipe->GetReadFd(); + if ( pipeFD == wxPipe::INVALID_FD ) { - wxLogSysError(_("Failed to switch wake up pipe to non-blocking mode")); - return false; + wxDELETE(m_wakeupPipe); + m_dispatcher = NULL; + return; } - wxLogTrace(TRACE_EVENTS, wxT("Wake up pipe (%d, %d) created"), - fdRead, m_pipe[wxPipe::Write]); - - return true; -} - -// ---------------------------------------------------------------------------- -// wakeup handling -// ---------------------------------------------------------------------------- + m_dispatcher = wxFDIODispatcher::Get(); + if ( !m_dispatcher ) + return; -void PipeIOHandler::WakeUp() -{ - if ( write(m_pipe[wxPipe::Write], "s", 1) != 1 ) - { - // don't use wxLog here, we can be in another thread and this could - // result in dead locks - perror("write(wake up pipe)"); - } + m_dispatcher->RegisterFD(pipeFD, m_wakeupPipe, wxFDIO_INPUT); } -void PipeIOHandler::OnReadWaiting() +wxConsoleEventLoop::~wxConsoleEventLoop() { - // got wakeup from child thread: read all data available in pipe just to - // 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 ( ;; ) + if ( m_wakeupPipe ) { - const int size = read(GetReadFd(), buf, WXSIZEOF(buf)); - - if ( size == 0 || (size == -1 && (errno == EAGAIN || errno == EINTR)) ) + if ( m_dispatcher ) { - // nothing left in the pipe (EAGAIN is expected for an FD with - // O_NONBLOCK) - break; + m_dispatcher->UnregisterFD(m_wakeupPipe->GetReadFd()); } - if ( size == -1 ) - { - wxLogSysError(_("Failed to read from wake-up pipe")); - - break; - } + delete m_wakeupPipe; } - - // 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 -// =========================================================================== - //----------------------------------------------------------------------------- -// initialization +// adding & removing sources //----------------------------------------------------------------------------- -wxConsoleEventLoop::wxConsoleEventLoop() +#if wxUSE_EVENTLOOP_SOURCE + +class wxConsoleEventLoopSourcesManager : public wxEventLoopSourcesManagerBase { - m_wakeupPipe = new wxPrivate::PipeIOHandler(); - if ( !m_wakeupPipe->Create() ) +public: + wxEventLoopSource* AddSourceForFD( int fd, + wxEventLoopSourceHandler *handler, + int flags) { - wxDELETE(m_wakeupPipe); - m_dispatcher = NULL; - return; + wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" ); + + wxLogTrace(wxTRACE_EVT_SOURCE, + "Adding event loop source for fd=%d", fd); + + // we need a bridge to wxFDIODispatcher + // + // TODO: refactor the code so that only wxEventLoopSourceHandler is used + wxScopedPtr + fdioHandler(new wxFDIOEventLoopSourceHandler(handler)); + + if ( !wxFDIODispatcher::Get()->RegisterFD(fd, fdioHandler.get(), flags) ) + return NULL; + + return new wxUnixEventLoopSource(wxFDIODispatcher::Get(), fdioHandler.release(), + fd, handler, flags); } +}; - m_dispatcher = wxFDIODispatcher::Get(); - if ( !m_dispatcher ) - return; +wxEventLoopSourcesManagerBase* wxAppTraits::GetEventLoopSourcesManager() +{ + static wxConsoleEventLoopSourcesManager s_eventLoopSourcesManager; - m_dispatcher->RegisterFD - ( - m_wakeupPipe->GetReadFd(), - m_wakeupPipe, - wxFDIO_INPUT - ); + return &s_eventLoopSourcesManager; } -wxConsoleEventLoop::~wxConsoleEventLoop() +wxUnixEventLoopSource::~wxUnixEventLoopSource() { - delete m_wakeupPipe; + wxLogTrace(wxTRACE_EVT_SOURCE, + "Removing event loop source for fd=%d", m_fd); + + m_dispatcher->UnregisterFD(m_fd); + + delete m_fdioHandler; } +#endif // wxUSE_EVENTLOOP_SOURCE + //----------------------------------------------------------------------------- // events dispatch and loop handling //-----------------------------------------------------------------------------