From bd7cea0ea609f032877f9435feba2623fce98db7 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 3 Jul 2013 00:27:53 +0000 Subject: [PATCH] Split wxWakeUpPipe class in MT-unsafe and MT-safe parts. This class can also be useful when it's used in the main thread only, so leave the lock-less part of the code in wxWakeUpPipe and derive a separate wxWakeUpPipeMT from it for the use in wxConsoleEventLoop where it can be used by multiple threads. See #10258. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74339 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/unix/evtloop.h | 4 +-- include/wx/unix/private/wakeuppipe.h | 47 ++++++++++++++++++++++++---- src/unix/evtloopunix.cpp | 2 +- src/unix/wakeuppipe.cpp | 6 +--- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/include/wx/unix/evtloop.h b/include/wx/unix/evtloop.h index 972b3f7838..5f1cf59ea1 100644 --- a/include/wx/unix/evtloop.h +++ b/include/wx/unix/evtloop.h @@ -19,7 +19,7 @@ class wxFDIODispatcher; class wxUnixEventLoopSource; -class wxWakeUpPipe; +class wxWakeUpPipeMT; class WXDLLIMPEXP_BASE wxConsoleEventLoop #ifdef __WXOSX__ @@ -52,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 - wxWakeUpPipe *m_wakeupPipe; + wxWakeUpPipeMT *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 index 2a942d05d7..b2dda1635c 100644 --- a/include/wx/unix/private/wakeuppipe.h +++ b/include/wx/unix/private/wakeuppipe.h @@ -19,6 +19,9 @@ // wxWakeUpPipe: allows to wake up the event loop by writing to it // ---------------------------------------------------------------------------- +// This class is not MT-safe, see wxWakeUpPipeMT below for a wake up pipe +// usable from other threads. + class wxWakeUpPipe : public wxFDIOHandler { public: @@ -32,9 +35,11 @@ public: // // 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(); + // As indicated by its name, this method does no locking and so can be + // called only from the main thread. + void WakeUpNoLock(); + + // Same as WakeUp() but without locking. // Return the read end of the pipe. int GetReadFd() { return m_pipe[wxPipe::Read]; } @@ -48,9 +53,6 @@ public: 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 @@ -58,4 +60,37 @@ private: bool m_pipeIsEmpty; }; +// ---------------------------------------------------------------------------- +// wxWakeUpPipeMT: thread-safe version of wxWakeUpPipe +// ---------------------------------------------------------------------------- + +// This class can be used from multiple threads, i.e. its WakeUp() can be +// called concurrently. + +class wxWakeUpPipeMT : public wxWakeUpPipe +{ +public: + wxWakeUpPipeMT() { } + + // Thread-safe wrapper around WakeUpNoLock(): can be called from another + // thread to wake up the main one. + void WakeUp() + { + wxCriticalSectionLocker lock(m_pipeLock); + + WakeUpNoLock(); + } + + virtual void OnReadWaiting() + { + wxCriticalSectionLocker lock(m_pipeLock); + + wxWakeUpPipe::OnReadWaiting(); + } + +private: + // Protects access to m_pipeIsEmpty. + wxCriticalSection m_pipeLock; +}; + #endif // _WX_UNIX_PRIVATE_WAKEUPPIPE_H_ diff --git a/src/unix/evtloopunix.cpp b/src/unix/evtloopunix.cpp index b26c7a5950..95756ef530 100644 --- a/src/unix/evtloopunix.cpp +++ b/src/unix/evtloopunix.cpp @@ -51,7 +51,7 @@ wxConsoleEventLoop::wxConsoleEventLoop() { - m_wakeupPipe = new wxWakeUpPipe; + m_wakeupPipe = new wxWakeUpPipeMT; const int pipeFD = m_wakeupPipe->GetReadFd(); if ( pipeFD == wxPipe::INVALID_FD ) { diff --git a/src/unix/wakeuppipe.cpp b/src/unix/wakeuppipe.cpp index b8ff1f12a6..0b40a25357 100644 --- a/src/unix/wakeuppipe.cpp +++ b/src/unix/wakeuppipe.cpp @@ -69,10 +69,8 @@ wxWakeUpPipe::wxWakeUpPipe() // wakeup handling // ---------------------------------------------------------------------------- -void wxWakeUpPipe::WakeUp() +void wxWakeUpPipe::WakeUpNoLock() { - wxCriticalSectionLocker lock(m_pipeLock); - // No need to do anything if the pipe already contains something. if ( !m_pipeIsEmpty ) return; @@ -95,8 +93,6 @@ 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 ( ;; ) { -- 2.45.2