X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c2ca375c5620209d77a88d2d378bdcdedbc82e7e..07aaf32633ecf18ec3edfbb41793a112914792d0:/src/unix/timerunx.cpp diff --git a/src/unix/timerunx.cpp b/src/unix/timerunx.cpp index 12dc0bdf27..7ee1177c89 100644 --- a/src/unix/timerunx.cpp +++ b/src/unix/timerunx.cpp @@ -18,6 +18,8 @@ #include "wx/wxprec.h" +#if wxUSE_TIMER + #ifndef WX_PRECOMP #include "wx/log.h" #include "wx/module.h" @@ -27,7 +29,10 @@ #include "wx/event.h" #endif +#include "wx/apptrait.h" #include "wx/longlong.h" +#include "wx/time.h" +#include "wx/vector.h" #include #include @@ -35,7 +40,7 @@ #include "wx/unix/private/timer.h" #include "wx/listimpl.cpp" -WX_DEFINE_LIST(wxTimerList); +WX_DEFINE_LIST(wxTimerList) // trace mask for the debugging messages used here #define wxTrace_Timer wxT("timer") @@ -50,7 +55,7 @@ static inline wxString wxUsecClockAsString(wxUsecClock_t usec) #if wxUSE_LONGLONG return usec.ToString(); #else // wxUsecClock_t == double - return wxString::Format(_T("%.0f"), usec); + return wxString::Format(wxT("%.0f"), usec); #endif } @@ -82,7 +87,7 @@ void wxTimerScheduler::DoAddTimer(wxTimerSchedule *s) for ( node = m_timers.begin(); node != m_timers.end(); ++node ) { wxASSERT_MSG( (*node)->m_timer != s->m_timer, - _T("adding the same timer twice?") ); + wxT("adding the same timer twice?") ); if ( (*node)->m_expiration > s->m_expiration ) break; @@ -111,7 +116,7 @@ void wxTimerScheduler::RemoveTimer(wxUnixTimerImpl *timer) } } - wxFAIL_MSG( _T("removing inexistent timer?") ); + wxFAIL_MSG( wxT("removing inexistent timer?") ); } bool wxTimerScheduler::GetNext(wxUsecClock_t *remaining) const @@ -119,9 +124,9 @@ bool wxTimerScheduler::GetNext(wxUsecClock_t *remaining) const if ( m_timers.empty() ) return false; - wxCHECK_MSG( remaining, false, _T("NULL pointer") ); + wxCHECK_MSG( remaining, false, wxT("NULL pointer") ); - *remaining = (*m_timers.begin())->m_expiration - wxGetLocalTimeUsec(); + *remaining = (*m_timers.begin())->m_expiration - wxGetUTCTimeUSec(); if ( *remaining < 0 ) { // timer already expired, don't wait at all before notifying it @@ -131,16 +136,17 @@ bool wxTimerScheduler::GetNext(wxUsecClock_t *remaining) const return true; } -void wxTimerScheduler::NotifyExpired() +bool wxTimerScheduler::NotifyExpired() { if ( m_timers.empty() ) - return; + return false; - const wxUsecClock_t now = wxGetLocalTimeUsec(); + const wxUsecClock_t now = wxGetUTCTimeUSec(); - wxTimerList::iterator cur, - next; - for ( cur = m_timers.begin(); cur != m_timers.end(); cur = next ) + typedef wxVector TimerImpls; + TimerImpls toNotify; + for ( wxTimerList::iterator next, + cur = m_timers.begin(); cur != m_timers.end(); cur = next ) { wxTimerSchedule * const s = *cur; if ( s->m_expiration > now ) @@ -159,18 +165,43 @@ void wxTimerScheduler::NotifyExpired() wxUnixTimerImpl * const timer = s->m_timer; if ( timer->IsOneShot() ) { + // the timer needs to be stopped but don't call its Stop() from + // here as it would attempt to remove the timer from our list and + // we had already done it, so we just need to reset its state + timer->MarkStopped(); + // don't need it any more delete s; } else // reschedule the next timer expiration { - s->m_expiration += timer->GetInterval()*1000; + // always keep the expiration time in the future, i.e. base it on + // the current time instead of just offsetting it from the current + // expiration time because it could happen that we're late and the + // current expiration time is (far) in the past + s->m_expiration = now + timer->GetInterval()*1000; DoAddTimer(s); } - // and finally notify the timer - timer->Notify(); + // we can't notify the timer from this loop as the timer event handler + // could modify m_timers (for example, but not only, by stopping this + // timer) which would render our iterators invalid, so do it after the + // loop end + toNotify.push_back(timer); + } + + if ( toNotify.empty() ) + return false; + + for ( TimerImpls::const_iterator i = toNotify.begin(), + end = toNotify.end(); + i != end; + ++i ) + { + (*i)->Notify(); } + + return true; } // ============================================================================ @@ -188,7 +219,7 @@ bool wxUnixTimerImpl::Start(int milliseconds, bool oneShot) // notice that this will stop an already running timer wxTimerImpl::Start(milliseconds, oneShot); - wxTimerScheduler::Get().AddTimer(this, wxGetLocalTimeUsec() + m_milli*1000); + wxTimerScheduler::Get().AddTimer(this, wxGetUTCTimeUSec() + m_milli*1000); m_isRunning = true; return true; @@ -211,7 +242,7 @@ bool wxUnixTimerImpl::IsRunning() const wxUnixTimerImpl::~wxUnixTimerImpl() { - wxASSERT_MSG( !m_isRunning, _T("must have been stopped before") ); + wxASSERT_MSG( !m_isRunning, wxT("must have been stopped before") ); } // ============================================================================ @@ -234,18 +265,10 @@ IMPLEMENT_DYNAMIC_CLASS(wxTimerUnixModule, wxModule) // global functions // ============================================================================ -wxUsecClock_t wxGetLocalTimeUsec() +wxTimerImpl *wxConsoleAppTraits::CreateTimerImpl(wxTimer *timer) { -#ifdef HAVE_GETTIMEOFDAY - struct timeval tv; - if ( wxGetTimeOfDay(&tv) != -1 ) - { - wxUsecClock_t val = 1000000L; // usec/sec - val *= tv.tv_sec; - return val + tv.tv_usec; - } -#endif // HAVE_GETTIMEOFDAY - - return wxGetLocalTimeMillis() * 1000L; + return new wxUnixTimerImpl(timer); } +#endif // wxUSE_TIMER +