preparation for allowing to use wxTimer in wxBase (heavily modified patch 1113088):
1. Changed wxTimer to use wxTimerImpl 2. Added Unix-specific generic timer implementation 3. Added wxAppTraits::CreateTimerImpl() git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45544 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
251
src/unix/timerunx.cpp
Normal file
251
src/unix/timerunx.cpp
Normal file
@@ -0,0 +1,251 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: src/unix/timerunx.cpp
|
||||
// Purpose: wxTimer implementation for non-GUI applications under Unix
|
||||
// Author: Lukasz Michalski
|
||||
// Created: 15/01/2005
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2007 Lukasz Michalski
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/log.h"
|
||||
#include "wx/module.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/list.h"
|
||||
#include "wx/hashmap.h"
|
||||
#include "wx/event.h"
|
||||
#endif
|
||||
|
||||
#include "wx/longlong.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "wx/unix/private/timer.h"
|
||||
|
||||
#include "wx/listimpl.cpp"
|
||||
WX_DEFINE_LIST(wxTimerList);
|
||||
|
||||
// trace mask for the debugging messages used here
|
||||
#define wxTrace_Timer wxT("timer")
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// local functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// helper function to format wxUsecClock_t
|
||||
static inline wxString wxUsecClockAsString(wxUsecClock_t usec)
|
||||
{
|
||||
#if wxUSE_LONGLONG
|
||||
return usec.ToString();
|
||||
#else // wxUsecClock_t == double
|
||||
return wxString::Format(_T("%.0f"), usec);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// wxTimerScheduler implementation
|
||||
// ============================================================================
|
||||
|
||||
wxTimerScheduler *wxTimerScheduler::ms_instance = NULL;
|
||||
|
||||
wxTimerScheduler::~wxTimerScheduler()
|
||||
{
|
||||
for ( wxTimerList::iterator node = m_timers.begin();
|
||||
node != m_timers.end();
|
||||
++node )
|
||||
{
|
||||
delete *node;
|
||||
}
|
||||
}
|
||||
|
||||
void wxTimerScheduler::AddTimer(wxUnixTimerImpl *timer, wxUsecClock_t expiration)
|
||||
{
|
||||
DoAddTimer(new wxTimerSchedule(timer, expiration));
|
||||
}
|
||||
|
||||
void wxTimerScheduler::DoAddTimer(wxTimerSchedule *s)
|
||||
{
|
||||
// do an insertion sort to keep the list sorted in expiration order
|
||||
wxTimerList::iterator node;
|
||||
for ( node = m_timers.begin(); node != m_timers.end(); ++node )
|
||||
{
|
||||
wxASSERT_MSG( (*node)->m_timer != s->m_timer,
|
||||
_T("adding the same timer twice?") );
|
||||
|
||||
if ( (*node)->m_expiration > s->m_expiration )
|
||||
break;
|
||||
}
|
||||
|
||||
m_timers.insert(node, s);
|
||||
|
||||
wxLogTrace(wxTrace_Timer, wxT("Inserted timer %d expiring at %s"),
|
||||
s->m_timer->GetId(),
|
||||
wxUsecClockAsString(s->m_expiration).c_str());
|
||||
}
|
||||
|
||||
void wxTimerScheduler::RemoveTimer(wxUnixTimerImpl *timer)
|
||||
{
|
||||
wxLogTrace(wxTrace_Timer, wxT("Removing timer %d"), timer->GetId());
|
||||
|
||||
for ( wxTimerList::iterator node = m_timers.begin();
|
||||
node != m_timers.end();
|
||||
++node )
|
||||
{
|
||||
if ( (*node)->m_timer == timer )
|
||||
{
|
||||
delete *node;
|
||||
m_timers.erase(node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wxFAIL_MSG( _T("removing inexistent timer?") );
|
||||
}
|
||||
|
||||
bool wxTimerScheduler::GetNext(wxUsecClock_t *remaining) const
|
||||
{
|
||||
if ( m_timers.empty() )
|
||||
return false;
|
||||
|
||||
wxCHECK_MSG( remaining, false, _T("NULL pointer") );
|
||||
|
||||
*remaining = (*m_timers.begin())->m_expiration - wxGetLocalTimeUsec();
|
||||
if ( *remaining < 0 )
|
||||
{
|
||||
// timer already expired, don't wait at all before notifying it
|
||||
*remaining = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxTimerScheduler::NotifyExpired()
|
||||
{
|
||||
if ( m_timers.empty() )
|
||||
return;
|
||||
|
||||
const wxUsecClock_t now = wxGetLocalTimeUsec();
|
||||
|
||||
wxTimerList::iterator cur,
|
||||
next;
|
||||
for ( cur = m_timers.begin(); cur != m_timers.end(); cur = next )
|
||||
{
|
||||
wxTimerSchedule * const s = *cur;
|
||||
if ( s->m_expiration > now )
|
||||
{
|
||||
// as the list is sorted by expiration time, we can skip the rest
|
||||
break;
|
||||
}
|
||||
|
||||
// remember next as we will delete the node pointed to by cur
|
||||
next = cur;
|
||||
++next;
|
||||
|
||||
m_timers.erase(cur);
|
||||
|
||||
// check whether we need to keep this timer
|
||||
wxUnixTimerImpl * const timer = s->m_timer;
|
||||
if ( timer->IsOneShot() )
|
||||
{
|
||||
// don't need it any more
|
||||
delete s;
|
||||
}
|
||||
else // reschedule the next timer expiration
|
||||
{
|
||||
s->m_expiration += timer->GetInterval()*1000;
|
||||
DoAddTimer(s);
|
||||
}
|
||||
|
||||
// and finally notify the timer
|
||||
timer->Notify();
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// wxUnixTimerImpl implementation
|
||||
// ============================================================================
|
||||
|
||||
wxUnixTimerImpl::wxUnixTimerImpl(wxTimer* timer)
|
||||
: wxTimerImpl(timer)
|
||||
{
|
||||
m_isRunning = false;
|
||||
}
|
||||
|
||||
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);
|
||||
m_isRunning = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxUnixTimerImpl::Stop()
|
||||
{
|
||||
if ( m_isRunning )
|
||||
{
|
||||
wxTimerScheduler::Get().RemoveTimer(this);
|
||||
|
||||
m_isRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool wxUnixTimerImpl::IsRunning() const
|
||||
{
|
||||
return m_isRunning;
|
||||
}
|
||||
|
||||
wxUnixTimerImpl::~wxUnixTimerImpl()
|
||||
{
|
||||
wxASSERT_MSG( !m_isRunning, _T("must have been stopped before") );
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// wxTimerUnixModule: responsible for freeing the global timer scheduler
|
||||
// ============================================================================
|
||||
|
||||
class wxTimerUnixModule : public wxModule
|
||||
{
|
||||
public:
|
||||
wxTimerUnixModule() {}
|
||||
virtual bool OnInit() { return true; }
|
||||
virtual void OnExit() { wxTimerScheduler::Shutdown(); }
|
||||
|
||||
DECLARE_DYNAMIC_CLASS(wxTimerUnixModule)
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxTimerUnixModule, wxModule)
|
||||
|
||||
// ============================================================================
|
||||
// global functions
|
||||
// ============================================================================
|
||||
|
||||
wxUsecClock_t wxGetLocalTimeUsec()
|
||||
{
|
||||
#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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user