[
1573619 ] Fix for Reentrance problems in events
in slightly modified form.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41874
c3d73ce0-8a6f-49c7-b76d-
6d57e0e08775
// add an event to be processed later
void AddPendingEvent(wxEvent& event);
// add an event to be processed later
void AddPendingEvent(wxEvent& event);
- // process all pending events
void ProcessPendingEvents();
#if wxUSE_THREADS
void ProcessPendingEvents();
#if wxUSE_THREADS
void SetClientData( void *data ) { DoSetClientData(data); }
void *GetClientData() const { return DoGetClientData(); }
void SetClientData( void *data ) { DoSetClientData(data); }
void *GetClientData() const { return DoGetClientData(); }
+ // reentrance guard
+ void AllowReentrance( bool allow = true ) { m_reentranceAllowed = allow; }
+ bool IsReentranceAllowed() { return m_reentranceAllowed; }
+ bool IsEventHandlingInProgress() { return m_eventHandlingInProgress; }
+
// check if the given event table entry matches this event and call the
// handler if it does
//
// check if the given event table entry matches this event and call the
// handler if it does
//
+ bool m_reentranceAllowed; // Reentrance is allowed for this handler?
+ bool m_eventHandlingInProgress; // Eventhandling is in progress?
+
// Is event handler enabled?
bool m_enabled;
// Is event handler enabled?
bool m_enabled;
// iterate until the list becomes empty
wxList::compatibility_iterator node = wxPendingEvents->GetFirst();
// iterate until the list becomes empty
wxList::compatibility_iterator node = wxPendingEvents->GetFirst();
+
+ while (node &&
+ ((wxEvtHandler *)node->GetData())->IsEventHandlingInProgress() &&
+ ((wxEvtHandler *)node->GetData())->IsReentranceAllowed() == false)
+ {
+ // skip over event
+ node = node->GetNext();
+ }
+
while (node)
{
wxEvtHandler *handler = (wxEvtHandler *)node->GetData();
while (node)
{
wxEvtHandler *handler = (wxEvtHandler *)node->GetData();
wxENTER_CRIT_SECT( *wxPendingEventsLocker );
node = wxPendingEvents->GetFirst();
wxENTER_CRIT_SECT( *wxPendingEventsLocker );
node = wxPendingEvents->GetFirst();
+
+ while (node &&
+ ((wxEvtHandler *)node->GetData())->IsEventHandlingInProgress() &&
+ ((wxEvtHandler *)node->GetData())->IsReentranceAllowed() == false)
+ {
+ // skip over event
+ node = node->GetNext();
+ }
}
wxLEAVE_CRIT_SECT( *wxPendingEventsLocker );
}
wxLEAVE_CRIT_SECT( *wxPendingEventsLocker );
m_eventsLocker = new wxCriticalSection;
# endif
#endif
m_eventsLocker = new wxCriticalSection;
# endif
#endif
+ // reentrace not allowed by default
+ m_reentranceAllowed = false;
+ m_eventHandlingInProgress = false;
+
// no client data (yet)
m_clientData = NULL;
m_clientDataType = wxClientData_None;
// no client data (yet)
m_clientData = NULL;
m_clientDataType = wxClientData_None;
void wxEvtHandler::ProcessPendingEvents()
{
void wxEvtHandler::ProcessPendingEvents()
{
- // this method is only called by wxApp if this handler does have pending
- // events
+ // this method is only called by wxApp if this handler does have
+ // pending events
wxCHECK_RET( m_pendingEvents,
wxT("Please call wxApp::ProcessPendingEvents() instead") );
wxCHECK_RET( m_pendingEvents,
wxT("Please call wxApp::ProcessPendingEvents() instead") );
+
+ // eventhandling is now in progess
+ m_eventHandlingInProgress = true;
wxENTER_CRIT_SECT( Lock() );
wxENTER_CRIT_SECT( Lock() );
// It's importan we remove event from list before processing it.
// Else a nested event loop, for example from a modal dialog, might
// process the same event again.
// It's importan we remove event from list before processing it.
// Else a nested event loop, for example from a modal dialog, might
// process the same event again.
m_pendingEvents->Erase(node);
wxLEAVE_CRIT_SECT( Lock() );
ProcessEvent(*event);
m_pendingEvents->Erase(node);
wxLEAVE_CRIT_SECT( Lock() );
ProcessEvent(*event);
+
+ // eventhandling no longer in progess
+ m_eventHandlingInProgress = false;
+
delete event;
wxENTER_CRIT_SECT( Lock() );
delete event;
wxENTER_CRIT_SECT( Lock() );