From: Vadim Zeitlin Date: Wed, 3 Jul 2013 00:27:28 +0000 (+0000) Subject: Extract PipeIOHandler class into a header and rename to wxWakeUpPipe. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/2ccfebab0925dd4bd5ad1671ad290ebc3141d782 Extract PipeIOHandler class into a header and rename to wxWakeUpPipe. No real changes to the class, just make it possible to reuse it outside of Unix wxEventLoop code. See #10258. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74338 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/Makefile.in b/Makefile.in index 0e81d7b435..6ab453d691 100644 --- a/Makefile.in +++ b/Makefile.in @@ -836,6 +836,7 @@ ALL_BASE_SOURCES = \ src/unix/timerunx.cpp \ src/unix/threadpsx.cpp \ src/unix/utilsunx.cpp \ + src/unix/wakeuppipe.cpp \ src/unix/fswatcher_kqueue.cpp \ src/unix/mimetype.cpp \ src/unix/fswatcher_inotify.cpp \ @@ -2240,6 +2241,7 @@ COND_TOOLKIT_OSX_CARBON_BASE_OSX_SRC = \ src/unix/timerunx.cpp \ src/unix/threadpsx.cpp \ src/unix/utilsunx.cpp \ + src/unix/wakeuppipe.cpp \ src/unix/fswatcher_kqueue.cpp @COND_TOOLKIT_OSX_CARBON@BASE_OSX_SRC = $(COND_TOOLKIT_OSX_CARBON_BASE_OSX_SRC) COND_TOOLKIT_OSX_COCOA_BASE_OSX_SRC = \ @@ -2263,6 +2265,7 @@ COND_TOOLKIT_OSX_COCOA_BASE_OSX_SRC = \ src/unix/timerunx.cpp \ src/unix/threadpsx.cpp \ src/unix/utilsunx.cpp \ + src/unix/wakeuppipe.cpp \ src/unix/fswatcher_kqueue.cpp @COND_TOOLKIT_OSX_COCOA@BASE_OSX_SRC = $(COND_TOOLKIT_OSX_COCOA_BASE_OSX_SRC) COND_TOOLKIT_OSX_IPHONE_BASE_OSX_SRC = \ @@ -2286,6 +2289,7 @@ COND_TOOLKIT_OSX_IPHONE_BASE_OSX_SRC = \ src/unix/timerunx.cpp \ src/unix/threadpsx.cpp \ src/unix/utilsunx.cpp \ + src/unix/wakeuppipe.cpp \ src/unix/fswatcher_kqueue.cpp @COND_TOOLKIT_OSX_IPHONE@BASE_OSX_SRC = $(COND_TOOLKIT_OSX_IPHONE_BASE_OSX_SRC) COND_TOOLKIT_COCOA_BASE_OSX_SRC = \ @@ -2303,6 +2307,7 @@ COND_TOOLKIT_COCOA_BASE_OSX_SRC = \ src/unix/timerunx.cpp \ src/unix/threadpsx.cpp \ src/unix/utilsunx.cpp \ + src/unix/wakeuppipe.cpp \ src/unix/fswatcher_kqueue.cpp \ src/unix/mimetype.cpp \ src/osx/core/cfstring.cpp \ @@ -2326,6 +2331,7 @@ COND_TOOLKIT_GTK_BASE_OSX_SRC = \ src/unix/timerunx.cpp \ src/unix/threadpsx.cpp \ src/unix/utilsunx.cpp \ + src/unix/wakeuppipe.cpp \ src/unix/fswatcher_kqueue.cpp \ src/unix/mimetype.cpp \ src/osx/core/cfstring.cpp \ @@ -2349,6 +2355,7 @@ COND_TOOLKIT_X11_BASE_OSX_SRC = \ src/unix/timerunx.cpp \ src/unix/threadpsx.cpp \ src/unix/utilsunx.cpp \ + src/unix/wakeuppipe.cpp \ src/unix/fswatcher_kqueue.cpp \ src/unix/mimetype.cpp \ src/osx/core/cfstring.cpp \ @@ -2372,6 +2379,7 @@ COND_TOOLKIT_MOTIF_BASE_OSX_SRC = \ src/unix/timerunx.cpp \ src/unix/threadpsx.cpp \ src/unix/utilsunx.cpp \ + src/unix/wakeuppipe.cpp \ src/unix/fswatcher_kqueue.cpp \ src/unix/mimetype.cpp \ src/osx/core/cfstring.cpp \ @@ -2395,6 +2403,7 @@ COND_TOOLKIT__BASE_OSX_SRC = \ src/unix/timerunx.cpp \ src/unix/threadpsx.cpp \ src/unix/utilsunx.cpp \ + src/unix/wakeuppipe.cpp \ src/unix/fswatcher_kqueue.cpp \ src/unix/mimetype.cpp \ src/osx/core/cfstring.cpp \ @@ -4499,6 +4508,7 @@ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS = \ monodll_timerunx.o \ monodll_threadpsx.o \ monodll_utilsunx.o \ + monodll_wakeuppipe.o \ monodll_fswatcher_kqueue.o @COND_PLATFORM_MACOSX_1@__BASE_PLATFORM_SRC_OBJECTS = $(COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS) @COND_PLATFORM_MSDOS_1@__BASE_PLATFORM_SRC_OBJECTS = \ @@ -4533,6 +4543,7 @@ COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS = \ monodll_timerunx.o \ monodll_threadpsx.o \ monodll_utilsunx.o \ + monodll_wakeuppipe.o \ monodll_fswatcher_kqueue.o \ monodll_unix_mimetype.o \ monodll_fswatcher_inotify.o @@ -6745,6 +6756,7 @@ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_1 = \ monolib_timerunx.o \ monolib_threadpsx.o \ monolib_utilsunx.o \ + monolib_wakeuppipe.o \ monolib_fswatcher_kqueue.o @COND_PLATFORM_MACOSX_1@__BASE_PLATFORM_SRC_OBJECTS_1 = $(COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_1) @COND_PLATFORM_MSDOS_1@__BASE_PLATFORM_SRC_OBJECTS_1 \ @@ -6779,6 +6791,7 @@ COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS_1 = \ monolib_timerunx.o \ monolib_threadpsx.o \ monolib_utilsunx.o \ + monolib_wakeuppipe.o \ monolib_fswatcher_kqueue.o \ monolib_unix_mimetype.o \ monolib_fswatcher_inotify.o @@ -9044,6 +9057,7 @@ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_2 = \ basedll_timerunx.o \ basedll_threadpsx.o \ basedll_utilsunx.o \ + basedll_wakeuppipe.o \ basedll_fswatcher_kqueue.o @COND_PLATFORM_MACOSX_1@__BASE_PLATFORM_SRC_OBJECTS_2 = $(COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_2) @COND_PLATFORM_MSDOS_1@__BASE_PLATFORM_SRC_OBJECTS_2 \ @@ -9078,6 +9092,7 @@ COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS_2 = \ basedll_timerunx.o \ basedll_threadpsx.o \ basedll_utilsunx.o \ + basedll_wakeuppipe.o \ basedll_fswatcher_kqueue.o \ basedll_unix_mimetype.o \ basedll_fswatcher_inotify.o @@ -9144,6 +9159,7 @@ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_3 = \ baselib_timerunx.o \ baselib_threadpsx.o \ baselib_utilsunx.o \ + baselib_wakeuppipe.o \ baselib_fswatcher_kqueue.o @COND_PLATFORM_MACOSX_1@__BASE_PLATFORM_SRC_OBJECTS_3 = $(COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_3) @COND_PLATFORM_MSDOS_1@__BASE_PLATFORM_SRC_OBJECTS_3 \ @@ -9178,6 +9194,7 @@ COND_PLATFORM_UNIX_1___BASE_PLATFORM_SRC_OBJECTS_3 = \ baselib_timerunx.o \ baselib_threadpsx.o \ baselib_utilsunx.o \ + baselib_wakeuppipe.o \ baselib_fswatcher_kqueue.o \ baselib_unix_mimetype.o \ baselib_fswatcher_inotify.o @@ -18931,6 +18948,12 @@ monodll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONODLL_ODEP) @COND_PLATFORM_MACOSX_1@monodll_utilsunx.o: $(srcdir)/src/unix/utilsunx.cpp $(MONODLL_ODEP) @COND_PLATFORM_MACOSX_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/unix/utilsunx.cpp +@COND_PLATFORM_UNIX_1@monodll_wakeuppipe.o: $(srcdir)/src/unix/wakeuppipe.cpp $(MONODLL_ODEP) +@COND_PLATFORM_UNIX_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/unix/wakeuppipe.cpp + +@COND_PLATFORM_MACOSX_1@monodll_wakeuppipe.o: $(srcdir)/src/unix/wakeuppipe.cpp $(MONODLL_ODEP) +@COND_PLATFORM_MACOSX_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/unix/wakeuppipe.cpp + @COND_PLATFORM_UNIX_1@monodll_fswatcher_kqueue.o: $(srcdir)/src/unix/fswatcher_kqueue.cpp $(MONODLL_ODEP) @COND_PLATFORM_UNIX_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/unix/fswatcher_kqueue.cpp @@ -24790,6 +24813,12 @@ monolib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONOLIB_ODEP) @COND_PLATFORM_MACOSX_1@monolib_utilsunx.o: $(srcdir)/src/unix/utilsunx.cpp $(MONOLIB_ODEP) @COND_PLATFORM_MACOSX_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/unix/utilsunx.cpp +@COND_PLATFORM_UNIX_1@monolib_wakeuppipe.o: $(srcdir)/src/unix/wakeuppipe.cpp $(MONOLIB_ODEP) +@COND_PLATFORM_UNIX_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/unix/wakeuppipe.cpp + +@COND_PLATFORM_MACOSX_1@monolib_wakeuppipe.o: $(srcdir)/src/unix/wakeuppipe.cpp $(MONOLIB_ODEP) +@COND_PLATFORM_MACOSX_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/unix/wakeuppipe.cpp + @COND_PLATFORM_UNIX_1@monolib_fswatcher_kqueue.o: $(srcdir)/src/unix/fswatcher_kqueue.cpp $(MONOLIB_ODEP) @COND_PLATFORM_UNIX_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/unix/fswatcher_kqueue.cpp @@ -29062,6 +29091,12 @@ basedll_cocoa_utils.o: $(srcdir)/src/osx/cocoa/utils.mm $(BASEDLL_ODEP) @COND_PLATFORM_MACOSX_1@basedll_utilsunx.o: $(srcdir)/src/unix/utilsunx.cpp $(BASEDLL_ODEP) @COND_PLATFORM_MACOSX_1@ $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/unix/utilsunx.cpp +@COND_PLATFORM_UNIX_1@basedll_wakeuppipe.o: $(srcdir)/src/unix/wakeuppipe.cpp $(BASEDLL_ODEP) +@COND_PLATFORM_UNIX_1@ $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/unix/wakeuppipe.cpp + +@COND_PLATFORM_MACOSX_1@basedll_wakeuppipe.o: $(srcdir)/src/unix/wakeuppipe.cpp $(BASEDLL_ODEP) +@COND_PLATFORM_MACOSX_1@ $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/unix/wakeuppipe.cpp + @COND_PLATFORM_UNIX_1@basedll_fswatcher_kqueue.o: $(srcdir)/src/unix/fswatcher_kqueue.cpp $(BASEDLL_ODEP) @COND_PLATFORM_UNIX_1@ $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/unix/fswatcher_kqueue.cpp @@ -29569,6 +29604,12 @@ baselib_cocoa_utils.o: $(srcdir)/src/osx/cocoa/utils.mm $(BASELIB_ODEP) @COND_PLATFORM_MACOSX_1@baselib_utilsunx.o: $(srcdir)/src/unix/utilsunx.cpp $(BASELIB_ODEP) @COND_PLATFORM_MACOSX_1@ $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/unix/utilsunx.cpp +@COND_PLATFORM_UNIX_1@baselib_wakeuppipe.o: $(srcdir)/src/unix/wakeuppipe.cpp $(BASELIB_ODEP) +@COND_PLATFORM_UNIX_1@ $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/unix/wakeuppipe.cpp + +@COND_PLATFORM_MACOSX_1@baselib_wakeuppipe.o: $(srcdir)/src/unix/wakeuppipe.cpp $(BASELIB_ODEP) +@COND_PLATFORM_MACOSX_1@ $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/unix/wakeuppipe.cpp + @COND_PLATFORM_UNIX_1@baselib_fswatcher_kqueue.o: $(srcdir)/src/unix/fswatcher_kqueue.cpp $(BASELIB_ODEP) @COND_PLATFORM_UNIX_1@ $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/unix/fswatcher_kqueue.cpp diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index befd8fe351..9a12df6afd 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -73,6 +73,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/unix/timerunx.cpp src/unix/threadpsx.cpp src/unix/utilsunx.cpp + src/unix/wakeuppipe.cpp src/unix/fswatcher_kqueue.cpp diff --git a/include/wx/unix/evtloop.h b/include/wx/unix/evtloop.h index f2b0a102c8..972b3f7838 100644 --- a/include/wx/unix/evtloop.h +++ b/include/wx/unix/evtloop.h @@ -19,11 +19,7 @@ class wxFDIODispatcher; class wxUnixEventLoopSource; - -namespace wxPrivate -{ - class PipeIOHandler; -} +class wxWakeUpPipe; class WXDLLIMPEXP_BASE wxConsoleEventLoop #ifdef __WXOSX__ @@ -56,7 +52,7 @@ protected: private: // 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 - wxPrivate::PipeIOHandler *m_wakeupPipe; + wxWakeUpPipe *m_wakeupPipe; // either wxSelectDispatcher or wxEpollDispatcher wxFDIODispatcher *m_dispatcher; diff --git a/include/wx/unix/private/wakeuppipe.h b/include/wx/unix/private/wakeuppipe.h new file mode 100644 index 0000000000..2a942d05d7 --- /dev/null +++ b/include/wx/unix/private/wakeuppipe.h @@ -0,0 +1,61 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/unix/private/wakeuppipe.h +// Purpose: Helper class allowing to wake up the main thread. +// Author: Vadim Zeitlin +// Created: 2013-06-09 (extracted from src/unix/evtloopunix.cpp) +// RCS-ID: $Id$ +// Copyright: (c) 2013 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_UNIX_PRIVATE_WAKEUPPIPE_H_ +#define _WX_UNIX_PRIVATE_WAKEUPPIPE_H_ + +#include "wx/private/fdiohandler.h" + +#include "wx/unix/pipe.h" + +// ---------------------------------------------------------------------------- +// wxWakeUpPipe: allows to wake up the event loop by writing to it +// ---------------------------------------------------------------------------- + +class wxWakeUpPipe : public wxFDIOHandler +{ +public: + // Create and initialize the pipe. + // + // It's the callers responsibility to add the read end of this pipe, + // returned by GetReadFd(), to the code blocking on input. + wxWakeUpPipe(); + + // Wake up the blocking operation involving this pipe. + // + // It simply writes to the write end of the pipe. + // + // Notice that this method can be, and often is, called from another + // thread. + void WakeUp(); + + // Return the read end of the pipe. + 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; + + // Protects access to m_pipeIsEmpty. + wxCriticalSection m_pipeLock; + + // This flag is set to true after writing to the pipe and reset to false + // after reading from it in the main thread. Having it allows us to avoid + // overflowing the pipe with too many writes if the main thread can't keep + // up with reading from it. + bool m_pipeIsEmpty; +}; + +#endif // _WX_UNIX_PRIVATE_WAKEUPPIPE_H_ diff --git a/src/unix/evtloopunix.cpp b/src/unix/evtloopunix.cpp index a4f67ecad6..b26c7a5950 100644 --- a/src/unix/evtloopunix.cpp +++ b/src/unix/evtloopunix.cpp @@ -28,161 +28,19 @@ #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" #if wxUSE_EVENTLOOP_SOURCE #include "wx/evtloopsrc.h" #endif // wxUSE_EVENTLOOP_SOURCE -#define TRACE_EVENTS wxT("events") - -// =========================================================================== -// 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() : m_pipeIsEmpty(true) { } - - 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; - - // Protects access to m_pipeIsEmpty. - wxCriticalSection m_pipeLock; - - // This flag is set to true after writing to the pipe and reset to false - // after reading from it in the main thread. Having it allows us to avoid - // overflowing the pipe with too many writes if the main thread can't keep - // up with reading from it. - bool m_pipeIsEmpty; -}; - -// ---------------------------------------------------------------------------- -// initialization -// ---------------------------------------------------------------------------- - -bool PipeIOHandler::Create() -{ - if ( !m_pipe.Create() ) - { - wxLogError(_("Failed to create wake up pipe used by event loop.")); - return false; - } - - - if ( !m_pipe.MakeNonBlocking(wxPipe::Read) ) - { - wxLogSysError(_("Failed to switch wake up pipe to non-blocking mode")); - return false; - } - - wxLogTrace(TRACE_EVENTS, wxT("Wake up pipe (%d, %d) created"), - m_pipe[wxPipe::Read], m_pipe[wxPipe::Write]); - - return true; -} - -// ---------------------------------------------------------------------------- -// wakeup handling -// ---------------------------------------------------------------------------- - -void PipeIOHandler::WakeUp() -{ - wxCriticalSectionLocker lock(m_pipeLock); - - // No need to do anything if the pipe already contains something. - if ( !m_pipeIsEmpty ) - return; - - 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)"); - } - else - { - // We just wrote to it, so it's not empty any more. - m_pipeIsEmpty = false; - } -} - -void PipeIOHandler::OnReadWaiting() -{ - // got wakeup from child thread, remove the data that provoked it from the - // pipe - - wxCriticalSectionLocker lock(m_pipeLock); - - char buf[4]; - for ( ;; ) - { - const int size = read(GetReadFd(), buf, WXSIZEOF(buf)); - - if ( size > 0 ) - { - wxASSERT_MSG( size == 1, "Too many writes to wake-up pipe?" ); - - break; - } - - if ( size == 0 || (size == -1 && errno == EAGAIN) ) - { - // No data available, not an error (but still surprising, - // spurious wakeup?) - break; - } - - if ( errno == EINTR ) - { - // We were interrupted, try again. - continue; - } - - wxLogSysError(_("Failed to read from wake-up pipe")); - - return; - } - - // The pipe is empty now, so future calls to WakeUp() would need to write - // to it again. - m_pipeIsEmpty = true; - - // 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 // =========================================================================== @@ -193,8 +51,9 @@ void PipeIOHandler::OnReadWaiting() wxConsoleEventLoop::wxConsoleEventLoop() { - m_wakeupPipe = new wxPrivate::PipeIOHandler(); - if ( !m_wakeupPipe->Create() ) + m_wakeupPipe = new wxWakeUpPipe; + const int pipeFD = m_wakeupPipe->GetReadFd(); + if ( pipeFD == wxPipe::INVALID_FD ) { wxDELETE(m_wakeupPipe); m_dispatcher = NULL; @@ -205,12 +64,7 @@ wxConsoleEventLoop::wxConsoleEventLoop() if ( !m_dispatcher ) return; - m_dispatcher->RegisterFD - ( - m_wakeupPipe->GetReadFd(), - m_wakeupPipe, - wxFDIO_INPUT - ); + m_dispatcher->RegisterFD(pipeFD, m_wakeupPipe, wxFDIO_INPUT); } wxConsoleEventLoop::~wxConsoleEventLoop() diff --git a/src/unix/wakeuppipe.cpp b/src/unix/wakeuppipe.cpp new file mode 100644 index 0000000000..b8ff1f12a6 --- /dev/null +++ b/src/unix/wakeuppipe.cpp @@ -0,0 +1,137 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/unix/wakeuppipe.cpp +// Purpose: Implementation of wxWakeUpPipe class. +// Author: Vadim Zeitlin +// Created: 2013-06-09 (extracted from src/unix/evtloopunix.cpp) +// RCS-ID: $Id$ +// Copyright: (c) 2013 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP +#endif // WX_PRECOMP + +#include "wx/unix/private/wakeuppipe.h" + +#include + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +#define TRACE_EVENTS wxT("events") + +// ============================================================================ +// wxWakeUpPipe implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// initialization +// ---------------------------------------------------------------------------- + +wxWakeUpPipe::wxWakeUpPipe() +{ + m_pipeIsEmpty = true; + + if ( !m_pipe.Create() ) + { + wxLogError(_("Failed to create wake up pipe used by event loop.")); + return; + } + + + if ( !m_pipe.MakeNonBlocking(wxPipe::Read) ) + { + wxLogSysError(_("Failed to switch wake up pipe to non-blocking mode")); + return; + } + + wxLogTrace(TRACE_EVENTS, wxT("Wake up pipe (%d, %d) created"), + m_pipe[wxPipe::Read], m_pipe[wxPipe::Write]); +} + +// ---------------------------------------------------------------------------- +// wakeup handling +// ---------------------------------------------------------------------------- + +void wxWakeUpPipe::WakeUp() +{ + wxCriticalSectionLocker lock(m_pipeLock); + + // No need to do anything if the pipe already contains something. + if ( !m_pipeIsEmpty ) + return; + + 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)"); + } + else + { + // We just wrote to it, so it's not empty any more. + m_pipeIsEmpty = false; + } +} + +void wxWakeUpPipe::OnReadWaiting() +{ + // got wakeup from child thread, remove the data that provoked it from the + // pipe + + wxCriticalSectionLocker lock(m_pipeLock); + + char buf[4]; + for ( ;; ) + { + const int size = read(GetReadFd(), buf, WXSIZEOF(buf)); + + if ( size > 0 ) + { + wxASSERT_MSG( size == 1, "Too many writes to wake-up pipe?" ); + + break; + } + + if ( size == 0 || (size == -1 && errno == EAGAIN) ) + { + // No data available, not an error (but still surprising, + // spurious wakeup?) + break; + } + + if ( errno == EINTR ) + { + // We were interrupted, try again. + continue; + } + + wxLogSysError(_("Failed to read from wake-up pipe")); + + return; + } + + // The pipe is empty now, so future calls to WakeUp() would need to write + // to it again. + m_pipeIsEmpty = true; + + // 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 +}