add wxAppConsoleBase::DeletePendingEvents and wxEvtHandler::DeletePendingEvents.
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
This commit is contained in:
@@ -313,6 +313,9 @@ public:
|
||||
//to the list of the handlers with _delayed_ pending events
|
||||
void DelayPendingEventHandler(wxEvtHandler* toDelay);
|
||||
|
||||
// deletes the current pending events
|
||||
void DeletePendingEvents();
|
||||
|
||||
|
||||
// wxEventLoop redirections
|
||||
// ------------------------
|
||||
@@ -420,11 +423,17 @@ protected:
|
||||
// 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;
|
||||
|
||||
// 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
|
||||
@@ -432,6 +441,9 @@ protected:
|
||||
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
|
||||
|
@@ -2864,7 +2864,6 @@ public:
|
||||
// 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.
|
||||
@@ -2900,9 +2899,11 @@ public:
|
||||
void ProcessPendingEvents();
|
||||
// NOTE: uses ProcessEvent()
|
||||
|
||||
void DeletePendingEvents();
|
||||
|
||||
#if wxUSE_THREADS
|
||||
bool ProcessThreadEvent(const wxEvent& event);
|
||||
// NOTE: uses AddPendingEvent()
|
||||
// NOTE: uses AddPendingEvent(); call only from secondary threads
|
||||
#endif
|
||||
|
||||
|
||||
|
@@ -125,15 +125,35 @@ public:
|
||||
|
||||
/**
|
||||
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.
|
||||
|
||||
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();
|
||||
|
||||
/**
|
||||
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.
|
||||
|
||||
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;
|
||||
|
||||
|
@@ -533,7 +533,32 @@ public:
|
||||
@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.
|
||||
@@ -555,6 +580,9 @@ public:
|
||||
|
||||
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()
|
||||
*/
|
||||
|
@@ -132,6 +132,7 @@ wxAppConsoleBase::wxAppConsoleBase()
|
||||
{
|
||||
m_traits = NULL;
|
||||
m_mainLoop = NULL;
|
||||
m_bDoPendingEventProcessing = true;
|
||||
|
||||
ms_appInstance = static_cast<wxAppConsole *>(this);
|
||||
|
||||
@@ -415,17 +416,19 @@ bool wxAppConsoleBase::HasPendingEvents() const
|
||||
|
||||
void wxAppConsoleBase::SuspendProcessingOfPendingEvents()
|
||||
{
|
||||
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
// entering the critical section locks blocks calls to ProcessPendingEvents()
|
||||
m_bDoPendingEventProcessing = false;
|
||||
}
|
||||
|
||||
void wxAppConsoleBase::ResumeProcessingOfPendingEvents()
|
||||
{
|
||||
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
m_bDoPendingEventProcessing = true;
|
||||
}
|
||||
|
||||
void wxAppConsoleBase::ProcessPendingEvents()
|
||||
{
|
||||
if (!m_bDoPendingEventProcessing)
|
||||
return;
|
||||
|
||||
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||
|
||||
wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
|
||||
@@ -462,6 +465,21 @@ void wxAppConsoleBase::ProcessPendingEvents()
|
||||
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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@@ -1079,14 +1079,12 @@ wxEvtHandler::~wxEvtHandler()
|
||||
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);
|
||||
|
||||
DeletePendingEvents();
|
||||
|
||||
// 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 )
|
||||
m_pendingEvents = new wxList;
|
||||
m_pendingEvents = new wxList;
|
||||
|
||||
m_pendingEvents->Append(event);
|
||||
|
||||
@@ -1169,6 +1167,13 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
|
||||
wxWakeUpIdle();
|
||||
}
|
||||
|
||||
void wxEvtHandler::DeletePendingEvents()
|
||||
{
|
||||
if (m_pendingEvents)
|
||||
m_pendingEvents->DeleteContents(true);
|
||||
wxDELETE(m_pendingEvents);
|
||||
}
|
||||
|
||||
void wxEvtHandler::ProcessPendingEvents()
|
||||
{
|
||||
if (!wxTheApp)
|
||||
|
Reference in New Issue
Block a user