X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/53cda845db64db0d358f69443cf7edeb2360a048..3fff75338a0f7ba6a210aa330fee64c91f636bc8:/src/common/appbase.cpp diff --git a/src/common/appbase.cpp b/src/common/appbase.cpp index 14a4cf64da..4851b5ac80 100644 --- a/src/common/appbase.cpp +++ b/src/common/appbase.cpp @@ -115,6 +115,8 @@ wxAppInitializerFunction wxAppConsoleBase::ms_appInitFn = NULL; wxSocketManager *wxAppTraitsBase::ms_manager = NULL; +WXDLLIMPEXP_DATA_BASE(wxList) wxPendingDelete; + // ---------------------------------------------------------------------------- // wxEventLoopPtr // ---------------------------------------------------------------------------- @@ -264,7 +266,7 @@ wxAppTraits *wxAppConsoleBase::GetTraits() { m_traits = CreateTraits(); - wxASSERT_MSG( m_traits, _T("wxApp::CreateTraits() failed?") ); + wxASSERT_MSG( m_traits, wxT("wxApp::CreateTraits() failed?") ); } return m_traits; @@ -333,9 +335,19 @@ void wxAppConsoleBase::WakeUpIdle() bool wxAppConsoleBase::ProcessIdle() { - wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); + // synthesize an idle event and check if more of them are needed + wxIdleEvent event; + event.SetEventObject(this); + ProcessEvent(event); - return loop && loop->ProcessIdle(); + return event.MoreRequested(); +} + +bool wxAppConsoleBase::UsesEventLoop() const +{ + // in console applications we don't know whether we're going to have an + // event loop so assume we won't -- unless we already have one running + return wxEventLoopBase::GetActive() != NULL; } // ---------------------------------------------------------------------------- @@ -430,43 +442,46 @@ void wxAppConsoleBase::ResumeProcessingOfPendingEvents() void wxAppConsoleBase::ProcessPendingEvents() { - if (!m_bDoPendingEventProcessing) - return; + if ( m_bDoPendingEventProcessing ) + { + wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); - wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); + wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(), + "this helper list should be empty" ); - wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(), - "this helper list should be empty" ); + // iterate until the list becomes empty: the handlers remove themselves + // from it when they don't have any more pending events + while (!m_handlersWithPendingEvents.IsEmpty()) + { + // In ProcessPendingEvents(), new handlers might be added + // and we can safely leave the critical section here. + wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); - // iterate until the list becomes empty: the handlers remove themselves - // from it when they don't have any more pending events - while (!m_handlersWithPendingEvents.IsEmpty()) - { - // In ProcessPendingEvents(), new handlers might be added - // and we can safely leave the critical section here. - wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); + // NOTE: we always call ProcessPendingEvents() on the first event handler + // with pending events because handlers auto-remove themselves + // from this list (see RemovePendingEventHandler) if they have no + // more pending events. + m_handlersWithPendingEvents[0]->ProcessPendingEvents(); - // NOTE: we always call ProcessPendingEvents() on the first event handler - // with pending events because handlers auto-remove themselves - // from this list (see RemovePendingEventHandler) if they have no - // more pending events. - m_handlersWithPendingEvents[0]->ProcessPendingEvents(); + wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); + } - wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); - } + // now the wxHandlersWithPendingEvents is surely empty; however some event + // handlers may have moved themselves into wxHandlersWithPendingDelayedEvents + // because of a selective wxYield call in progress. + // Now we need to move them back to wxHandlersWithPendingEvents so the next + // call to this function has the chance of processing them: + if (!m_handlersWithPendingDelayedEvents.IsEmpty()) + { + WX_APPEND_ARRAY(m_handlersWithPendingEvents, m_handlersWithPendingDelayedEvents); + m_handlersWithPendingDelayedEvents.Clear(); + } - // now the wxHandlersWithPendingEvents is surely empty; however some event - // handlers may have moved themselves into wxHandlersWithPendingDelayedEvents - // because of a selective wxYield call in progress. - // Now we need to move them back to wxHandlersWithPendingEvents so the next - // call to this function has the chance of processing them: - if (!m_handlersWithPendingDelayedEvents.IsEmpty()) - { - WX_APPEND_ARRAY(m_handlersWithPendingEvents, m_handlersWithPendingDelayedEvents); - m_handlersWithPendingDelayedEvents.Clear(); + wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); } - wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); + // Garbage collect all objects previously scheduled for destruction. + DeletePendingObjects(); } void wxAppConsoleBase::DeletePendingEvents() @@ -484,6 +499,50 @@ void wxAppConsoleBase::DeletePendingEvents() wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); } +// ---------------------------------------------------------------------------- +// delayed objects destruction +// ---------------------------------------------------------------------------- + +bool wxAppConsoleBase::IsScheduledForDestruction(wxObject *object) const +{ + return wxPendingDelete.Member(object); +} + +void wxAppConsoleBase::ScheduleForDestruction(wxObject *object) +{ + if ( !UsesEventLoop() ) + { + // we won't be able to delete it later so do it right now + delete object; + return; + } + //else: we either already have or will soon start an event loop + + if ( !wxPendingDelete.Member(object) ) + wxPendingDelete.Append(object); +} + +void wxAppConsoleBase::DeletePendingObjects() +{ + wxList::compatibility_iterator node = wxPendingDelete.GetFirst(); + while (node) + { + wxObject *obj = node->GetData(); + + // remove it from the list first so that if we get back here somehow + // during the object deletion (e.g. wxYield called from its dtor) we + // wouldn't try to delete it the second time + if ( wxPendingDelete.Member(obj) ) + wxPendingDelete.Erase(node); + + delete obj; + + // Deleting one object may have deleted other pending + // objects, so start from beginning of list again. + node = wxPendingDelete.GetFirst(); + } +} + // ---------------------------------------------------------------------------- // exception handling // ---------------------------------------------------------------------------- @@ -647,7 +706,7 @@ bool wxAppConsoleBase::CheckBuildOptions(const char *optionsSignature, wxString progName = wxString::FromAscii(componentName); wxString msg; - msg.Printf(_T("Mismatch between the program and library build versions detected.\nThe library used %s,\nand %s used %s."), + msg.Printf(wxT("Mismatch between the program and library build versions detected.\nThe library used %s,\nand %s used %s."), lib.c_str(), progName.c_str(), prog.c_str()); wxLogFatalError(msg.c_str()); @@ -735,16 +794,6 @@ bool wxConsoleAppTraitsBase::HasStderr() return true; } -void wxConsoleAppTraitsBase::ScheduleForDestroy(wxObject *object) -{ - delete object; -} - -void wxConsoleAppTraitsBase::RemoveFromPendingDelete(wxObject * WXUNUSED(object)) -{ - // nothing to do -} - // ---------------------------------------------------------------------------- // wxAppTraits // ---------------------------------------------------------------------------- @@ -801,7 +850,7 @@ bool wxAppTraitsBase::ShowAssertDialog(const wxString& msgOriginal) const wxString stackTrace = GetAssertStackTrace(); if ( !stackTrace.empty() ) - msg << _T("\n\nCall stack:\n") << stackTrace; + msg << wxT("\n\nCall stack:\n") << stackTrace; #endif // wxUSE_STACKWALKER return DoShowAssertDialog(msg); @@ -830,29 +879,29 @@ wxString wxAppTraitsBase::GetAssertStackTrace() { m_stackTrace << wxString::Format ( - _T("[%02d] "), + wxT("[%02d] "), wx_truncate_cast(int, frame.GetLevel()) ); wxString name = frame.GetName(); if ( !name.empty() ) { - m_stackTrace << wxString::Format(_T("%-40s"), name.c_str()); + m_stackTrace << wxString::Format(wxT("%-40s"), name.c_str()); } else { - m_stackTrace << wxString::Format(_T("%p"), frame.GetAddress()); + m_stackTrace << wxString::Format(wxT("%p"), frame.GetAddress()); } if ( frame.HasSourceLocation() ) { - m_stackTrace << _T('\t') + m_stackTrace << wxT('\t') << frame.GetFileName() - << _T(':') + << wxT(':') << frame.GetLine(); } - m_stackTrace << _T('\n'); + m_stackTrace << wxT('\n'); } private: @@ -1084,7 +1133,7 @@ bool DoShowAssertDialog(const wxString& msg) wxT("You can also choose [Cancel] to suppress ") wxT("further warnings."); - switch ( ::MessageBox(NULL, msgDlg.wx_str(), _T("wxWidgets Debug Alert"), + switch ( ::MessageBox(NULL, msgDlg.wx_str(), wxT("wxWidgets Debug Alert"), MB_YESNOCANCEL | MB_ICONSTOP ) ) { case IDYES: @@ -1131,16 +1180,16 @@ void ShowAssertDialog(const wxString& file, // add the function name, if any if ( !func.empty() ) - msg << _T(" in ") << func << _T("()"); + msg << wxT(" in ") << func << wxT("()"); // and the message itself if ( !msgUser.empty() ) { - msg << _T(": ") << msgUser; + msg << wxT(": ") << msgUser; } else // no message given { - msg << _T('.'); + msg << wxT('.'); } #if wxUSE_THREADS @@ -1167,7 +1216,7 @@ void ShowAssertDialog(const wxString& file, if ( !s_bNoAsserts ) { // send it to the normal log destination - wxLogDebug(_T("%s"), msg.c_str()); + wxLogDebug(wxT("%s"), msg.c_str()); if ( traits ) {