From fe593cc504195a3c91281eae4edf5e852a51a59c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Thu, 4 Nov 2004 20:04:59 +0000 Subject: [PATCH] (hopefully) fixed race condition in installing idle handler (calling wxPostEvent from non-main thread) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30266 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/gtk/app.h | 2 ++ include/wx/gtk1/app.h | 2 ++ src/gtk/app.cpp | 36 +++++++++++++++++++++++++++++++----- src/gtk/evtloop.cpp | 3 +-- src/gtk1/app.cpp | 36 +++++++++++++++++++++++++++++++----- src/gtk1/evtloop.cpp | 3 +-- 6 files changed, 68 insertions(+), 14 deletions(-) diff --git a/include/wx/gtk/app.h b/include/wx/gtk/app.h index 33b62e1c15..fd4fa6226b 100644 --- a/include/wx/gtk/app.h +++ b/include/wx/gtk/app.h @@ -56,6 +56,8 @@ public: #endif // __WXDEBUG__ gint m_idleTag; + void RemoveIdleTag(); + unsigned char *m_colorCube; // Used by the the wxGLApp and wxGLCanvas class for GL-based X visual diff --git a/include/wx/gtk1/app.h b/include/wx/gtk1/app.h index 33b62e1c15..fd4fa6226b 100644 --- a/include/wx/gtk1/app.h +++ b/include/wx/gtk1/app.h @@ -56,6 +56,8 @@ public: #endif // __WXDEBUG__ gint m_idleTag; + void RemoveIdleTag(); + unsigned char *m_colorCube; // Used by the the wxGLApp and wxGLCanvas class for GL-based X visual diff --git a/src/gtk/app.cpp b/src/gtk/app.cpp index 86822b5abd..5aa26126a7 100644 --- a/src/gtk/app.cpp +++ b/src/gtk/app.cpp @@ -34,6 +34,7 @@ #include "wx/filename.h" #include "wx/module.h" #include "wx/image.h" +#include "wx/thread.h" #ifdef __WXGPE__ #include @@ -97,6 +98,10 @@ extern bool g_isIdle; void wxapp_install_idle_handler(); +#if wxUSE_THREADS +static wxMutex gs_idleTagsMutex; +#endif + //----------------------------------------------------------------------------- // wxYield //----------------------------------------------------------------------------- @@ -132,8 +137,7 @@ bool wxApp::Yield(bool onlyIfNeeded) { // We need to remove idle callbacks or the loop will // never finish. - gtk_idle_remove( m_idleTag ); - m_idleTag = 0; + wxTheApp->RemoveIdleTag(); g_isIdle = TRUE; } @@ -211,7 +215,12 @@ static gint wxapp_pending_callback( gpointer WXUNUSED(data) ) // Sent idle event to all who request them. wxTheApp->ProcessPendingEvents(); - g_pendingTag = 0; + { +#if wxUSE_THREADS + wxMutexLocker lock(gs_idleTagsMutex); +#endif + g_pendingTag = 0; + } // Flush the logged messages if any. #if wxUSE_LOG @@ -259,8 +268,13 @@ static gint wxapp_idle_callback( gpointer WXUNUSED(data) ) // Indicate that we are now in idle mode and event handlers // will have to reinstall the idle handler again. - g_isIdle = TRUE; - wxTheApp->m_idleTag = 0; + { +#if wxUSE_THREADS + wxMutexLocker lock(gs_idleTagsMutex); +#endif + g_isIdle = TRUE; + wxTheApp->m_idleTag = 0; + } // Send idle event to all who request them as long as // no events have popped up in the event queue. @@ -368,6 +382,10 @@ static gint wxapp_poll_func( GPollFD *ufds, guint nfds, gint timeout ) void wxapp_install_idle_handler() { +#if wxUSE_THREADS + wxMutexLocker lock(gs_idleTagsMutex); +#endif + // GD: this assert is raised when using the thread sample (which works) // so the test is probably not so easy. Can widget callbacks be // triggered from child threads and, if so, for which widgets? @@ -679,3 +697,11 @@ void wxApp::OnAssert(const wxChar *file, int line, const wxChar* cond, const wxC #endif // __WXDEBUG__ +void wxApp::RemoveIdleTag() +{ +#if wxUSE_THREADS + wxMutexLocker lock(gs_idleTagsMutex); +#endif + gtk_idle_remove( wxTheApp->m_idleTag ); + wxTheApp->m_idleTag = 0; +} diff --git a/src/gtk/evtloop.cpp b/src/gtk/evtloop.cpp index d89a31d44f..429de81069 100644 --- a/src/gtk/evtloop.cpp +++ b/src/gtk/evtloop.cpp @@ -109,8 +109,7 @@ bool wxEventLoop::Pending() const { // We need to remove idle callbacks or gtk_events_pending will // never return false. - gtk_idle_remove( wxTheApp->m_idleTag ); - wxTheApp->m_idleTag = 0; + wxTheApp->RemoveIdleTag(); g_isIdle = TRUE; } diff --git a/src/gtk1/app.cpp b/src/gtk1/app.cpp index 86822b5abd..5aa26126a7 100644 --- a/src/gtk1/app.cpp +++ b/src/gtk1/app.cpp @@ -34,6 +34,7 @@ #include "wx/filename.h" #include "wx/module.h" #include "wx/image.h" +#include "wx/thread.h" #ifdef __WXGPE__ #include @@ -97,6 +98,10 @@ extern bool g_isIdle; void wxapp_install_idle_handler(); +#if wxUSE_THREADS +static wxMutex gs_idleTagsMutex; +#endif + //----------------------------------------------------------------------------- // wxYield //----------------------------------------------------------------------------- @@ -132,8 +137,7 @@ bool wxApp::Yield(bool onlyIfNeeded) { // We need to remove idle callbacks or the loop will // never finish. - gtk_idle_remove( m_idleTag ); - m_idleTag = 0; + wxTheApp->RemoveIdleTag(); g_isIdle = TRUE; } @@ -211,7 +215,12 @@ static gint wxapp_pending_callback( gpointer WXUNUSED(data) ) // Sent idle event to all who request them. wxTheApp->ProcessPendingEvents(); - g_pendingTag = 0; + { +#if wxUSE_THREADS + wxMutexLocker lock(gs_idleTagsMutex); +#endif + g_pendingTag = 0; + } // Flush the logged messages if any. #if wxUSE_LOG @@ -259,8 +268,13 @@ static gint wxapp_idle_callback( gpointer WXUNUSED(data) ) // Indicate that we are now in idle mode and event handlers // will have to reinstall the idle handler again. - g_isIdle = TRUE; - wxTheApp->m_idleTag = 0; + { +#if wxUSE_THREADS + wxMutexLocker lock(gs_idleTagsMutex); +#endif + g_isIdle = TRUE; + wxTheApp->m_idleTag = 0; + } // Send idle event to all who request them as long as // no events have popped up in the event queue. @@ -368,6 +382,10 @@ static gint wxapp_poll_func( GPollFD *ufds, guint nfds, gint timeout ) void wxapp_install_idle_handler() { +#if wxUSE_THREADS + wxMutexLocker lock(gs_idleTagsMutex); +#endif + // GD: this assert is raised when using the thread sample (which works) // so the test is probably not so easy. Can widget callbacks be // triggered from child threads and, if so, for which widgets? @@ -679,3 +697,11 @@ void wxApp::OnAssert(const wxChar *file, int line, const wxChar* cond, const wxC #endif // __WXDEBUG__ +void wxApp::RemoveIdleTag() +{ +#if wxUSE_THREADS + wxMutexLocker lock(gs_idleTagsMutex); +#endif + gtk_idle_remove( wxTheApp->m_idleTag ); + wxTheApp->m_idleTag = 0; +} diff --git a/src/gtk1/evtloop.cpp b/src/gtk1/evtloop.cpp index d89a31d44f..429de81069 100644 --- a/src/gtk1/evtloop.cpp +++ b/src/gtk1/evtloop.cpp @@ -109,8 +109,7 @@ bool wxEventLoop::Pending() const { // We need to remove idle callbacks or gtk_events_pending will // never return false. - gtk_idle_remove( wxTheApp->m_idleTag ); - wxTheApp->m_idleTag = 0; + wxTheApp->RemoveIdleTag(); g_isIdle = TRUE; }