From 7214297d16aed4c160c1cbef6b19f153ca065ab7 Mon Sep 17 00:00:00 2001 From: Guilhem Lavaux Date: Sat, 27 Mar 1999 18:50:54 +0000 Subject: [PATCH] * Added threads event propagation. Should compile on GTK (tested). git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@1986 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/event.h | 21 +++++++++++---- include/wx/gtk/app.h | 3 +++ include/wx/gtk1/app.h | 3 +++ include/wx/motif/app.h | 3 +++ include/wx/msw/app.h | 3 +++ src/common/event.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++ src/gtk/app.cpp | 27 +++++++++++++++++++ src/gtk/data.cpp | 6 +++++ src/gtk1/app.cpp | 27 +++++++++++++++++++ src/gtk1/data.cpp | 6 +++++ src/motif/app.cpp | 27 +++++++++++++++++++ src/motif/data.cpp | 6 +++++ src/msw/app.cpp | 29 ++++++++++++++++++++ src/msw/data.cpp | 6 +++++ 14 files changed, 223 insertions(+), 5 deletions(-) diff --git a/include/wx/event.h b/include/wx/event.h index 2ac0ea2fe0..24a0d2b4f1 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -19,6 +19,9 @@ #include "wx/defs.h" #include "wx/object.h" #include "wx/gdicmn.h" +#if wxUSE_THREADS +#include "wx/thread.h" +#endif /* * Event types @@ -347,7 +350,7 @@ public: // Set/Get listbox/choice selection string void SetString(const wxString& s) { m_commandString = s; } - const wxString& GetString() const { return m_commandString; } + wxString GetString() const { return m_commandString; } // Get checkbox value bool Checked() const { return (m_commandInt != 0); } @@ -1170,6 +1173,10 @@ public: virtual bool OnClose(); #endif +#if wxUSE_THREADS + bool ProcessThreadEvent(wxEvent& event); + void ProcessPendingEvents(); +#endif virtual bool ProcessEvent(wxEvent& event); virtual bool SearchEventTable(wxEventTable& table, wxEvent& event); @@ -1196,10 +1203,14 @@ protected: virtual const wxEventTable *GetEventTable() const; protected: - wxEvtHandler* m_nextHandler; - wxEvtHandler* m_previousHandler; - bool m_enabled; // Is event handler enabled? - wxList* m_dynamicEvents; + wxEvtHandler* m_nextHandler; + wxEvtHandler* m_previousHandler; + bool m_enabled; // Is event handler enabled? + wxList* m_dynamicEvents; + wxList* m_pendingEvents; +#if wxUSE_THREADS + wxCriticalSection* m_eventsLocker; +#endif // optimization: instead of using costly IsKindOf() to decide whether we're // a window (which is true in 99% of cases), use this flag diff --git a/include/wx/gtk/app.h b/include/wx/gtk/app.h index 365c08f90a..ac36884cfe 100644 --- a/include/wx/gtk/app.h +++ b/include/wx/gtk/app.h @@ -115,6 +115,9 @@ class wxApp: public wxEvtHandler static void CleanUp(); bool ProcessIdle(); +#if wxUSE_THREADS + void ProcessPendingEvents(); +#endif void DeletePendingObjects(); bool m_initialized; diff --git a/include/wx/gtk1/app.h b/include/wx/gtk1/app.h index 365c08f90a..ac36884cfe 100644 --- a/include/wx/gtk1/app.h +++ b/include/wx/gtk1/app.h @@ -115,6 +115,9 @@ class wxApp: public wxEvtHandler static void CleanUp(); bool ProcessIdle(); +#if wxUSE_THREADS + void ProcessPendingEvents(); +#endif void DeletePendingObjects(); bool m_initialized; diff --git a/include/wx/motif/app.h b/include/wx/motif/app.h index 5cbe5267fa..2b24418913 100644 --- a/include/wx/motif/app.h +++ b/include/wx/motif/app.h @@ -141,6 +141,9 @@ public: void DeletePendingObjects(); bool ProcessIdle(); +#if wxUSE_THREADS + void ProcessPendingEvents(); +#endif // Motif-specific inline WXAppContext GetAppContext() const { return m_appContext; } diff --git a/include/wx/msw/app.h b/include/wx/msw/app.h index f299a952ea..c5cbcfcd06 100644 --- a/include/wx/msw/app.h +++ b/include/wx/msw/app.h @@ -144,6 +144,9 @@ public: virtual bool ProcessMessage(WXMSG* pMsg); void DeletePendingObjects(); bool ProcessIdle(); +#if wxUSE_THREADS + void ProcessPendingEvents(); +#endif int GetComCtl32Version() const; public: diff --git a/src/common/event.cpp b/src/common/event.cpp index 713c0fdac6..a1123fdf19 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -78,6 +78,12 @@ #endif // !USE_SHARED_LIBRARY +#if wxUSE_THREADS +/* To put pending event handlers */ +extern wxList wxPendingEvents; +extern wxCriticalSection wxPendingEventsLocker; +#endif + /* * General wxWindows events, covering * all interesting things that might happen (button clicking, resizing, @@ -283,6 +289,10 @@ wxEvtHandler::wxEvtHandler() m_enabled = TRUE; m_dynamicEvents = (wxList *) NULL; m_isWindow = FALSE; +#if wxUSE_THREADS + m_eventsLocker = new wxCriticalSection(); +#endif + m_pendingEvents = (wxList *) NULL; } wxEvtHandler::~wxEvtHandler() @@ -306,8 +316,54 @@ wxEvtHandler::~wxEvtHandler() } delete m_dynamicEvents; }; + + if (m_pendingEvents) + delete m_pendingEvents; + +#if wxUSE_THREADS + delete m_eventsLocker; +#endif } +#if wxUSE_THREADS +bool wxEvtHandler::ProcessThreadEvent(wxEvent& event) +{ + wxEvent *event_main; + wxCriticalSectionLocker locker(*m_eventsLocker); + + // check that we are really in a child thread + wxASSERT( !wxThread::IsMain() ); + + if (m_pendingEvents == NULL) + m_pendingEvents = new wxList(); + + event_main = (wxEvent *)event.GetClassInfo()->CreateObject(); + *event_main = event; + + m_pendingEvents->Append(event_main); + + wxPendingEventsLocker.Enter(); + wxPendingEvents.Append(this); + wxPendingEventsLocker.Leave(); + + return TRUE; +} + +void wxEvtHandler::ProcessPendingEvents() +{ + wxCriticalSectionLocker locker(*m_eventsLocker); + wxNode *node = m_pendingEvents->First(); + wxEvent *event; + + while (node != NULL) { + event = (wxEvent *)node->Data(); + ProcessEvent(*event); + delete node; + node = m_pendingEvents->First(); + } +} +#endif + /* * Event table stuff */ @@ -320,6 +376,11 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event) // An event handler can be enabled or disabled if ( GetEvtHandlerEnabled() ) { +#if wxUSE_THREADS + // Check whether we are in a child thread. + if (!wxThread::IsMain()) + return ProcessThreadEvent(event); +#endif // Handle per-instance dynamic event tables first if ( m_dynamicEvents && SearchDynamicEventTable(event) ) diff --git a/src/gtk/app.cpp b/src/gtk/app.cpp index afe49ce3c1..93459c373d 100644 --- a/src/gtk/app.cpp +++ b/src/gtk/app.cpp @@ -46,6 +46,10 @@ wxApp *wxTheApp = (wxApp *) NULL; wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL; extern wxList wxPendingDelete; +#if wxUSE_THREADS +extern wxList wxPendingEvents; +extern wxCriticalSection wxPendingEventsLocker; +#endif extern wxResourceCache *wxTheResourceCache; unsigned char g_palette[64*3] = @@ -283,6 +287,10 @@ void wxApp::OnIdle( wxIdleEvent &event ) inOnIdle = TRUE; + /* Resend in the main thread events which have been prepared in other + threads */ + ProcessPendingEvents(); + /* 'Garbage' collection of windows deleted with Close(). */ DeletePendingObjects(); @@ -366,6 +374,25 @@ void wxApp::Dispatch() { } +#if wxUSE_THREADS +void wxApp::ProcessPendingEvents() +{ + wxNode *node = wxPendingEvents.First(); + wxCriticalSectionLocker locker(wxPendingEventsLocker); + + while (node) + { + wxEvtHandler *handler = (wxEvtHandler *)node->Data(); + + handler->ProcessPendingEvents(); + + delete node; + + node = wxPendingEvents.First(); + } +} +#endif + void wxApp::DeletePendingObjects() { wxNode *node = wxPendingDelete.First(); diff --git a/src/gtk/data.cpp b/src/gtk/data.cpp index 39b6114278..f8c868a247 100644 --- a/src/gtk/data.cpp +++ b/src/gtk/data.cpp @@ -38,6 +38,12 @@ wxList wxTopLevelWindows; /* List of windows pending deletion */ wxList wxPendingDelete; +#if wxUSE_THREADS +/* List of events pending processing */ +wxList wxPendingEvents; +wxCriticalSection wxPendingEventsLocker; +#endif + /* Current cursor, in order to hang on to * cursor handle when setting the cursor globally */ wxCursor *g_globalCursor = (wxCursor *) NULL; diff --git a/src/gtk1/app.cpp b/src/gtk1/app.cpp index afe49ce3c1..93459c373d 100644 --- a/src/gtk1/app.cpp +++ b/src/gtk1/app.cpp @@ -46,6 +46,10 @@ wxApp *wxTheApp = (wxApp *) NULL; wxAppInitializerFunction wxApp::m_appInitFn = (wxAppInitializerFunction) NULL; extern wxList wxPendingDelete; +#if wxUSE_THREADS +extern wxList wxPendingEvents; +extern wxCriticalSection wxPendingEventsLocker; +#endif extern wxResourceCache *wxTheResourceCache; unsigned char g_palette[64*3] = @@ -283,6 +287,10 @@ void wxApp::OnIdle( wxIdleEvent &event ) inOnIdle = TRUE; + /* Resend in the main thread events which have been prepared in other + threads */ + ProcessPendingEvents(); + /* 'Garbage' collection of windows deleted with Close(). */ DeletePendingObjects(); @@ -366,6 +374,25 @@ void wxApp::Dispatch() { } +#if wxUSE_THREADS +void wxApp::ProcessPendingEvents() +{ + wxNode *node = wxPendingEvents.First(); + wxCriticalSectionLocker locker(wxPendingEventsLocker); + + while (node) + { + wxEvtHandler *handler = (wxEvtHandler *)node->Data(); + + handler->ProcessPendingEvents(); + + delete node; + + node = wxPendingEvents.First(); + } +} +#endif + void wxApp::DeletePendingObjects() { wxNode *node = wxPendingDelete.First(); diff --git a/src/gtk1/data.cpp b/src/gtk1/data.cpp index 39b6114278..f8c868a247 100644 --- a/src/gtk1/data.cpp +++ b/src/gtk1/data.cpp @@ -38,6 +38,12 @@ wxList wxTopLevelWindows; /* List of windows pending deletion */ wxList wxPendingDelete; +#if wxUSE_THREADS +/* List of events pending processing */ +wxList wxPendingEvents; +wxCriticalSection wxPendingEventsLocker; +#endif + /* Current cursor, in order to hang on to * cursor handle when setting the cursor globally */ wxCursor *g_globalCursor = (wxCursor *) NULL; diff --git a/src/motif/app.cpp b/src/motif/app.cpp index ba8f0da012..65859d3f7b 100644 --- a/src/motif/app.cpp +++ b/src/motif/app.cpp @@ -49,6 +49,10 @@ extern char *wxBuffer; extern wxList wxPendingDelete; +#if wxUSE_THREADS +extern wxList wxPendingEvents; +extern wxList wxPendingEventsLocker; +#endif wxApp *wxTheApp = NULL; @@ -411,6 +415,11 @@ void wxApp::OnIdle(wxIdleEvent& event) // 'Garbage' collection of windows deleted with Close(). DeletePendingObjects(); +#if wxUSE_THREADS + // Flush pending events. + ProcessPendingEvents(); +#endif + // flush the logged messages if any wxLog *pLog = wxLog::GetActiveTarget(); if ( pLog != NULL && pLog->HasPendingMessages() ) @@ -483,6 +492,24 @@ void wxApp::DeletePendingObjects() } } +#if wxUSE_THREADS +void wxApp::ProcessPendingEvents() + + wxNode *node = wxPendingEvents.First(); + wxCriticalSectionLocker locker(wxPendingEventsLocker); + + while (node) + { + wxEvtHandler *handler = (wxEvtHandler *)node->Data(); + + handler->ProcessPendingEvents(); + + delete node; + node = wxPendingEvents.First(); + } + +#endif + wxLog* wxApp::CreateLogTarget() { return new wxLogGui; diff --git a/src/motif/data.cpp b/src/motif/data.cpp index bbe4fe2ad7..4767438a1c 100644 --- a/src/motif/data.cpp +++ b/src/motif/data.cpp @@ -27,6 +27,12 @@ wxList wxTopLevelWindows; // List of windows pending deletion wxList wxPendingDelete; +#if wxUSE_THREADS +// List of events pending propagation +wxList wxPendingEvents; +wxCriticalSection wxPendingEventsLocker; +#endif + int wxPageNumber; // GDI Object Lists diff --git a/src/msw/app.cpp b/src/msw/app.cpp index 3ea5ea7362..21dd1dbecc 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -92,6 +92,10 @@ extern char *wxBuffer; extern char *wxOsVersion; extern wxList *wxWinHandleList; extern wxList WXDLLEXPORT wxPendingDelete; +#if wxUSE_THREADS +extern wxList wxPendingEvents; +extern wxCriticalSection wxPendingEventsLocker; +#endif extern void wxSetKeyboardHook(bool doIt); extern wxCursor *g_globalCursor; @@ -893,7 +897,13 @@ int wxApp::MainLoop() { } + DoMessage(); + + // If they are pending events, we must process them. +#if wxUSE_THREADS + ProcessPendingEvents(); +#endif } return s_currentMsg.wParam; @@ -909,6 +919,25 @@ bool wxApp::ProcessIdle() return event.MoreRequested(); } +#if wxUSE_THREADS +void wxApp::ProcessPendingEvents() + + wxNode *node = wxPendingEvents.First(); + wxCriticalSectionLocker locker(wxPendingEventsLocker); + + while (node) + { + wxEvtHandler *handler = (wxEvtHandler *)node->Data(); + + handler->ProcessPendingEvents(); + + delete node; + node = wxPendingEvents.First(); + } +} +#endif + + void wxApp::ExitMainLoop() { m_keepGoing = FALSE; diff --git a/src/msw/data.cpp b/src/msw/data.cpp index e7e0283111..439c73cd49 100644 --- a/src/msw/data.cpp +++ b/src/msw/data.cpp @@ -37,6 +37,12 @@ wxList wxTopLevelWindows; // List of windows pending deletion wxList WXDLLEXPORT wxPendingDelete; +// List of events pending processing +#if wxUSE_THREADS +wxList wxPendingEvents; +wxCriticalSection wxPendingEventsLocker; +#endif + // Current cursor, in order to hang on to // cursor handle when setting the cursor globally wxCursor *g_globalCursor = NULL; -- 2.45.2