wxSocketManager *wxAppTraitsBase::ms_manager = NULL;
+WXDLLIMPEXP_DATA_BASE(wxList) wxPendingDelete;
+
// ----------------------------------------------------------------------------
// wxEventLoopPtr
// ----------------------------------------------------------------------------
{
m_traits = CreateTraits();
- wxASSERT_MSG( m_traits, _T("wxApp::CreateTraits() failed?") );
+ wxASSERT_MSG( m_traits, wxT("wxApp::CreateTraits() failed?") );
}
return m_traits;
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;
+}
+
// ----------------------------------------------------------------------------
// events
// ----------------------------------------------------------------------------
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()
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
// ----------------------------------------------------------------------------
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());
return true;
}
-void wxConsoleAppTraitsBase::ScheduleForDestroy(wxObject *object)
-{
- delete object;
-}
-
-void wxConsoleAppTraitsBase::RemoveFromPendingDelete(wxObject * WXUNUSED(object))
-{
- // nothing to do
-}
-
// ----------------------------------------------------------------------------
// wxAppTraits
// ----------------------------------------------------------------------------
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);
{
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:
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:
// 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
if ( !s_bNoAsserts )
{
// send it to the normal log destination
- wxLogDebug(_T("%s"), msg.c_str());
+ wxLogDebug(wxT("%s"), msg.c_str());
if ( traits )
{