]>
git.saurik.com Git - wxWidgets.git/blob - src/unix/timerunx.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/unix/timerunx.cpp 
   3 // Purpose:     wxTimer implementation for non-GUI applications under Unix 
   4 // Author:      Lukasz Michalski 
   7 // Copyright:   (c) 2007 Lukasz Michalski 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  11 // ============================================================================ 
  13 // ============================================================================ 
  15 // ---------------------------------------------------------------------------- 
  17 // ---------------------------------------------------------------------------- 
  19 #include "wx/wxprec.h" 
  25     #include "wx/module.h" 
  28     #include "wx/hashmap.h" 
  32 #include "wx/apptrait.h" 
  33 #include "wx/longlong.h" 
  38 #include "wx/unix/private/timer.h" 
  40 #include "wx/listimpl.cpp" 
  41 WX_DEFINE_LIST(wxTimerList
) 
  43 // trace mask for the debugging messages used here 
  44 #define wxTrace_Timer wxT("timer") 
  46 // ---------------------------------------------------------------------------- 
  48 // ---------------------------------------------------------------------------- 
  50 // helper function to format wxUsecClock_t 
  51 static inline wxString 
wxUsecClockAsString(wxUsecClock_t usec
) 
  54         return usec
.ToString(); 
  55     #else // wxUsecClock_t == double 
  56         return wxString::Format(_T("%.0f"), usec
); 
  60 // ============================================================================ 
  61 // wxTimerScheduler implementation 
  62 // ============================================================================ 
  64 wxTimerScheduler 
*wxTimerScheduler::ms_instance 
= NULL
; 
  66 wxTimerScheduler::~wxTimerScheduler() 
  68     for ( wxTimerList::iterator node 
= m_timers
.begin(); 
  69           node 
!= m_timers
.end(); 
  76 void wxTimerScheduler::AddTimer(wxUnixTimerImpl 
*timer
, wxUsecClock_t expiration
) 
  78     DoAddTimer(new wxTimerSchedule(timer
, expiration
)); 
  81 void wxTimerScheduler::DoAddTimer(wxTimerSchedule 
*s
) 
  83     // do an insertion sort to keep the list sorted in expiration order 
  84     wxTimerList::iterator node
; 
  85     for ( node 
= m_timers
.begin(); node 
!= m_timers
.end(); ++node 
) 
  87         wxASSERT_MSG( (*node
)->m_timer 
!= s
->m_timer
, 
  88                       _T("adding the same timer twice?") ); 
  90         if ( (*node
)->m_expiration 
> s
->m_expiration 
) 
  94     m_timers
.insert(node
, s
); 
  96     wxLogTrace(wxTrace_Timer
, wxT("Inserted timer %d expiring at %s"), 
  98                wxUsecClockAsString(s
->m_expiration
).c_str()); 
 101 void wxTimerScheduler::RemoveTimer(wxUnixTimerImpl 
*timer
) 
 103     wxLogTrace(wxTrace_Timer
, wxT("Removing timer %d"), timer
->GetId()); 
 105     for ( wxTimerList::iterator node 
= m_timers
.begin(); 
 106           node 
!= m_timers
.end(); 
 109         if ( (*node
)->m_timer 
== timer 
) 
 112             m_timers
.erase(node
); 
 117     wxFAIL_MSG( _T("removing inexistent timer?") ); 
 120 bool wxTimerScheduler::GetNext(wxUsecClock_t 
*remaining
) const 
 122     if ( m_timers
.empty() ) 
 125     wxCHECK_MSG( remaining
, false, _T("NULL pointer") ); 
 127     *remaining 
= (*m_timers
.begin())->m_expiration 
- wxGetLocalTimeUsec(); 
 128     if ( *remaining 
< 0 ) 
 130         // timer already expired, don't wait at all before notifying it 
 137 bool wxTimerScheduler::NotifyExpired() 
 139     if ( m_timers
.empty() ) 
 142     bool notified 
= false; 
 144     const wxUsecClock_t now 
= wxGetLocalTimeUsec(); 
 146     wxTimerList::iterator cur
, 
 148     for ( cur 
= m_timers
.begin(); cur 
!= m_timers
.end(); cur 
= next 
) 
 150         wxTimerSchedule 
* const s 
= *cur
; 
 151         if ( s
->m_expiration 
> now 
) 
 153             // as the list is sorted by expiration time, we can skip the rest 
 157         // remember next as we will delete the node pointed to by cur 
 163         // check whether we need to keep this timer 
 164         wxUnixTimerImpl 
* const timer 
= s
->m_timer
; 
 165         if ( timer
->IsOneShot() ) 
 167             // the timer needs to be stopped but don't call its Stop() from 
 168             // here as it would attempt to remove the timer from our list and 
 169             // we had already done it, so we just need to reset its state 
 170             timer
->MarkStopped(); 
 172             // don't need it any more 
 175         else // reschedule the next timer expiration 
 177             // always keep the expiration time in the future, i.e. base it on 
 178             // the current time instead of just offsetting it from the current 
 179             // expiration time because it could happen that we're late and the 
 180             // current expiration time is (far) in the past 
 181             s
->m_expiration 
= now 
+ timer
->GetInterval()*1000; 
 185         // and finally notify the timer 
 193 // ============================================================================ 
 194 // wxUnixTimerImpl implementation 
 195 // ============================================================================ 
 197 wxUnixTimerImpl::wxUnixTimerImpl(wxTimer
* timer
) 
 203 bool wxUnixTimerImpl::Start(int milliseconds
, bool oneShot
) 
 205     // notice that this will stop an already running timer 
 206     wxTimerImpl::Start(milliseconds
, oneShot
); 
 208     wxTimerScheduler::Get().AddTimer(this, wxGetLocalTimeUsec() + m_milli
*1000); 
 214 void wxUnixTimerImpl::Stop() 
 218         wxTimerScheduler::Get().RemoveTimer(this); 
 224 bool wxUnixTimerImpl::IsRunning() const 
 229 wxUnixTimerImpl::~wxUnixTimerImpl() 
 231     wxASSERT_MSG( !m_isRunning
, _T("must have been stopped before") ); 
 234 // ============================================================================ 
 235 // wxTimerUnixModule: responsible for freeing the global timer scheduler 
 236 // ============================================================================ 
 238 class wxTimerUnixModule 
: public wxModule
 
 241     wxTimerUnixModule() {} 
 242     virtual bool OnInit() { return true; } 
 243     virtual void OnExit() { wxTimerScheduler::Shutdown(); } 
 245     DECLARE_DYNAMIC_CLASS(wxTimerUnixModule
) 
 248 IMPLEMENT_DYNAMIC_CLASS(wxTimerUnixModule
, wxModule
) 
 250 // ============================================================================ 
 252 // ============================================================================ 
 254 wxUsecClock_t 
wxGetLocalTimeUsec() 
 256 #ifdef HAVE_GETTIMEOFDAY 
 258     if ( wxGetTimeOfDay(&tv
) != -1 ) 
 260         wxUsecClock_t val 
= 1000000L; // usec/sec 
 262         return val 
+ tv
.tv_usec
; 
 264 #endif // HAVE_GETTIMEOFDAY 
 266     return wxGetLocalTimeMillis() * 1000L; 
 269 wxTimerImpl 
*wxConsoleAppTraits::CreateTimerImpl(wxTimer 
*timer
) 
 271     return new wxUnixTimerImpl(timer
); 
 274 #endif // wxUSE_TIMER