]> git.saurik.com Git - wxWidgets.git/commitdiff
add wxAppConsoleBase::DeletePendingEvents and wxEvtHandler::DeletePendingEvents.
authorFrancesco Montorsi <f18m_cpp217828@yahoo.it>
Sun, 8 Mar 2009 12:58:24 +0000 (12:58 +0000)
committerFrancesco Montorsi <f18m_cpp217828@yahoo.it>
Sun, 8 Mar 2009 12:58:24 +0000 (12:58 +0000)
Fix wxAppConsoleBase::Suspend/ResumeProcessingOfPendingEvents: locking the mutex does not prevent wxAppConsoleBase::ProcessPendingEvents from running if the mutex was locked from the main thread!

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59433 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/app.h
include/wx/event.h
interface/wx/app.h
interface/wx/event.h
src/common/appbase.cpp
src/common/event.cpp

index 1a9a083f5e6ffc979bd0f2efea2a505946875c26..5e0e97060ed65b27896dfc14ca060c2787f5e09a 100644 (file)
@@ -313,6 +313,9 @@ public:
     //to the list of the handlers with _delayed_ pending events
     void DelayPendingEventHandler(wxEvtHandler* toDelay);
 
     //to the list of the handlers with _delayed_ pending events
     void DelayPendingEventHandler(wxEvtHandler* toDelay);
 
+    // deletes the current pending events
+    void DeletePendingEvents();
+
 
     // wxEventLoop redirections
     // ------------------------
 
     // wxEventLoop redirections
     // ------------------------
@@ -420,11 +423,17 @@ protected:
     // been started yet or has already terminated)
     wxEventLoopBase *m_mainLoop;
 
     // been started yet or has already terminated)
     wxEventLoopBase *m_mainLoop;
 
+
+    // pending events management vars:
+
     // the array of the handlers with pending events which needs to be processed
     // inside ProcessPendingEvents()
     wxEvtHandlerArray m_handlersWithPendingEvents;
 
     // the array of the handlers with pending events which needs to be processed
     // inside ProcessPendingEvents()
     wxEvtHandlerArray m_handlersWithPendingEvents;
 
-    // helper array used by ProcessPendingEvents()
+    // helper array used by ProcessPendingEvents() to store the event handlers
+    // which have pending events but of these events none can be processed right now
+    // (because of a call to wxEventLoop::YieldFor() which asked to selectively process
+    // pending events)
     wxEvtHandlerArray m_handlersWithPendingDelayedEvents;
 
 #if wxUSE_THREADS
     wxEvtHandlerArray m_handlersWithPendingDelayedEvents;
 
 #if wxUSE_THREADS
@@ -432,6 +441,9 @@ protected:
     wxCriticalSection m_handlersWithPendingEventsLocker;
 #endif
 
     wxCriticalSection m_handlersWithPendingEventsLocker;
 #endif
 
+    // flag modified by Suspend/ResumeProcessingOfPendingEvents()
+    bool m_bDoPendingEventProcessing;
+
     friend class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
 
     // the application object is a singleton anyhow, there is no sense in
     friend class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
 
     // the application object is a singleton anyhow, there is no sense in
index ad6469b9582853ad86897234211a7af1cf6f8efd..259694172e9dc1dac5847eef669b5e7ea8797ffc 100644 (file)
@@ -2864,7 +2864,6 @@ public:
     // Event queuing and processing
     // ----------------------------
 
     // Event queuing and processing
     // ----------------------------
 
-
     // Process an event right now: this can only be called from the main
     // thread, use QueueEvent() for scheduling the events for
     // processing from other threads.
     // Process an event right now: this can only be called from the main
     // thread, use QueueEvent() for scheduling the events for
     // processing from other threads.
@@ -2900,9 +2899,11 @@ public:
     void ProcessPendingEvents();
         // NOTE: uses ProcessEvent()
 
     void ProcessPendingEvents();
         // NOTE: uses ProcessEvent()
 
+    void DeletePendingEvents();
+
 #if wxUSE_THREADS
     bool ProcessThreadEvent(const wxEvent& event);
 #if wxUSE_THREADS
     bool ProcessThreadEvent(const wxEvent& event);
-        // NOTE: uses AddPendingEvent()
+        // NOTE: uses AddPendingEvent(); call only from secondary threads
 #endif
 
 
 #endif
 
 
index 9d358c7473d131a69679b6dc12a19b17bf780ae8..7bc9844834e2b60b3936e2ffe3701efc7038355d 100644 (file)
@@ -125,15 +125,35 @@ public:
 
     /**
         Process all pending events; it is necessary to call this function to
 
     /**
         Process all pending events; it is necessary to call this function to
-        process posted events.
+        process events posted with wxEvtHandler::QueueEvent or wxEvtHandler::AddPendingEvent.
 
 
-        This happens during each event loop iteration in GUI mode but
+        This happens during each event loop iteration (see wxEventLoopBase) in GUI mode but
         it may be also called directly.
         it may be also called directly.
+        
+        Note that this function does not only process the pending events for the wxApp object
+        itself (which derives from wxEvtHandler) but also the pending events for @e any
+        event handler of this application.
+        
+        This function will immediately return and do nothing if SuspendProcessingOfPendingEvents()
+        was called.
     */
     virtual void ProcessPendingEvents();
     */
     virtual void ProcessPendingEvents();
+    
+    /**
+        Deletes the pending events of all wxEvtHandlers of this application.
+        
+        See wxEvtHandler::DeletePendingEvents() for warnings about deleting the pending
+        events.
+    */
+    void DeletePendingEvents();
 
     /**
         Returns @true if there are pending events on the internal pending event list.
 
     /**
         Returns @true if there are pending events on the internal pending event list.
+        
+        Whenever wxEvtHandler::QueueEvent or wxEvtHandler::AddPendingEvent() are
+        called (not only for wxApp itself, but for any event handler of the application!), 
+        the internal wxApp's list of handlers with pending events is updated and this
+        function will return true.
     */
     bool HasPendingEvents() const;
 
     */
     bool HasPendingEvents() const;
 
index 2e80f9c739d75460d2032c60e3961376d43d33db..548ceffb062f035eb8a3fc141a11c4406ca72206 100644 (file)
@@ -533,7 +533,32 @@ public:
         @see wxWindow::HandleWindowEvent
     */
     bool SafelyProcessEvent(wxEvent& event);
         @see wxWindow::HandleWindowEvent
     */
     bool SafelyProcessEvent(wxEvent& event);
+    
+    /**
+        Processes the pending events previously queued using QueueEvent() or 
+        AddPendingEvent(); you must call this function only if you are sure
+        there are pending events for this handler, otherwise a @c wxCHECK
+        will fail.
+        
+        The real processing still happens in ProcessEvent() which is called by this
+        function.
+        
+        Note that this function needs a valid application object (see 
+        wxAppConsole::GetInstance()) because wxApp holds the list of the event
+        handlers with pending events and this function manipulates that list.
+    */
+    void ProcessPendingEvents();
 
 
+    /**
+        Deletes all events queued on this event handler using QueueEvent() or
+        AddPendingEvent().
+        
+        Use with care because the events which are deleted are (obviously) not
+        processed and this may have unwanted consequences (e.g. user actions events
+        will be lost).
+    */
+    void DeletePendingEvents();
+    
     /**
         Searches the event table, executing an event handler function if an appropriate
         one is found.
     /**
         Searches the event table, executing an event handler function if an appropriate
         one is found.
@@ -555,6 +580,9 @@ public:
 
                  If a suitable function is called but calls wxEvent::Skip, this
                  function will fail, and searching will continue.
 
                  If a suitable function is called but calls wxEvent::Skip, this
                  function will fail, and searching will continue.
+                 
+         @todo this function in the header is listed as an "implementation only" function;
+               are we sure we want to document it?
 
         @see ProcessEvent()
     */
 
         @see ProcessEvent()
     */
index a78e93d1d47c42776f266653f4a0363e0f157c77..111ff3c7afac4a95e3057e26cf591199c1bf3871 100644 (file)
@@ -132,6 +132,7 @@ wxAppConsoleBase::wxAppConsoleBase()
 {
     m_traits = NULL;
     m_mainLoop = NULL;
 {
     m_traits = NULL;
     m_mainLoop = NULL;
+    m_bDoPendingEventProcessing = true;
 
     ms_appInstance = static_cast<wxAppConsole *>(this);
 
 
     ms_appInstance = static_cast<wxAppConsole *>(this);
 
@@ -415,17 +416,19 @@ bool wxAppConsoleBase::HasPendingEvents() const
 
 void wxAppConsoleBase::SuspendProcessingOfPendingEvents()
 {
 
 void wxAppConsoleBase::SuspendProcessingOfPendingEvents()
 {
-    wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
-        // entering the critical section locks blocks calls to ProcessPendingEvents()
+    m_bDoPendingEventProcessing = false;
 }
 
 void wxAppConsoleBase::ResumeProcessingOfPendingEvents()
 {
 }
 
 void wxAppConsoleBase::ResumeProcessingOfPendingEvents()
 {
-    wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
+    m_bDoPendingEventProcessing = true;
 }
 
 void wxAppConsoleBase::ProcessPendingEvents()
 {
 }
 
 void wxAppConsoleBase::ProcessPendingEvents()
 {
+    if (!m_bDoPendingEventProcessing)
+        return;
+
     wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
 
     wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
     wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
 
     wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
@@ -462,6 +465,21 @@ void wxAppConsoleBase::ProcessPendingEvents()
     wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
 }
 
     wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
 }
 
+void wxAppConsoleBase::DeletePendingEvents()
+{
+    wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
+
+    wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
+                 "this helper list should be empty" );
+
+    for (unsigned int i=0; i<m_handlersWithPendingEvents.GetCount(); i++)
+        m_handlersWithPendingEvents[i]->DeletePendingEvents();
+
+    m_handlersWithPendingEvents.Clear();
+
+    wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
+}
+
 // ----------------------------------------------------------------------------
 // exception handling
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // exception handling
 // ----------------------------------------------------------------------------
index 7118b7dbd9697166ea770f42424b775862e79f35..461b6fe5e783ace86af812afe81ab06ebbc988d8 100644 (file)
@@ -1079,14 +1079,12 @@ wxEvtHandler::~wxEvtHandler()
         delete m_dynamicEvents;
     }
 
         delete m_dynamicEvents;
     }
 
-    if (m_pendingEvents)
-        m_pendingEvents->DeleteContents(true);
-    delete m_pendingEvents;
-
     // Remove us from the list of the pending events if necessary.
     if (wxTheApp)
         wxTheApp->RemovePendingEventHandler(this);
 
     // Remove us from the list of the pending events if necessary.
     if (wxTheApp)
         wxTheApp->RemovePendingEventHandler(this);
 
+    DeletePendingEvents();
+
     // we only delete object data, not untyped
     if ( m_clientDataType == wxClientData_Object )
         delete m_clientObject;
     // we only delete object data, not untyped
     if ( m_clientDataType == wxClientData_Object )
         delete m_clientObject;
@@ -1147,7 +1145,7 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
     wxENTER_CRIT_SECT( m_pendingEventsLock );
 
     if ( !m_pendingEvents )
     wxENTER_CRIT_SECT( m_pendingEventsLock );
 
     if ( !m_pendingEvents )
-      m_pendingEvents = new wxList;
+        m_pendingEvents = new wxList;
 
     m_pendingEvents->Append(event);
 
 
     m_pendingEvents->Append(event);
 
@@ -1169,6 +1167,13 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
     wxWakeUpIdle();
 }
 
     wxWakeUpIdle();
 }
 
+void wxEvtHandler::DeletePendingEvents()
+{
+    if (m_pendingEvents)
+        m_pendingEvents->DeleteContents(true);
+    wxDELETE(m_pendingEvents);
+}
+
 void wxEvtHandler::ProcessPendingEvents()
 {
     if (!wxTheApp)
 void wxEvtHandler::ProcessPendingEvents()
 {
     if (!wxTheApp)