]>
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" 
  34 #include "wx/vector.h" 
  39 #include "wx/unix/private/timer.h" 
  41 #include "wx/listimpl.cpp" 
  42 WX_DEFINE_LIST(wxTimerList
) 
  44 // trace mask for the debugging messages used here 
  45 #define wxTrace_Timer wxT("timer") 
  47 // ---------------------------------------------------------------------------- 
  49 // ---------------------------------------------------------------------------- 
  51 // helper function to format wxUsecClock_t 
  52 static inline wxString 
wxUsecClockAsString(wxUsecClock_t usec
) 
  55         return usec
.ToString(); 
  56     #else // wxUsecClock_t == double 
  57         return wxString::Format(wxT("%.0f"), usec
); 
  61 // ============================================================================ 
  62 // wxTimerScheduler implementation 
  63 // ============================================================================ 
  65 wxTimerScheduler 
*wxTimerScheduler::ms_instance 
= NULL
; 
  67 wxTimerScheduler::~wxTimerScheduler() 
  69     for ( wxTimerList::iterator node 
= m_timers
.begin(); 
  70           node 
!= m_timers
.end(); 
  77 void wxTimerScheduler::AddTimer(wxUnixTimerImpl 
*timer
, wxUsecClock_t expiration
) 
  79     DoAddTimer(new wxTimerSchedule(timer
, expiration
)); 
  82 void wxTimerScheduler::DoAddTimer(wxTimerSchedule 
*s
) 
  84     // do an insertion sort to keep the list sorted in expiration order 
  85     wxTimerList::iterator node
; 
  86     for ( node 
= m_timers
.begin(); node 
!= m_timers
.end(); ++node 
) 
  88         wxASSERT_MSG( (*node
)->m_timer 
!= s
->m_timer
, 
  89                       wxT("adding the same timer twice?") ); 
  91         if ( (*node
)->m_expiration 
> s
->m_expiration 
) 
  95     m_timers
.insert(node
, s
); 
  97     wxLogTrace(wxTrace_Timer
, wxT("Inserted timer %d expiring at %s"), 
  99                wxUsecClockAsString(s
->m_expiration
).c_str()); 
 102 void wxTimerScheduler::RemoveTimer(wxUnixTimerImpl 
*timer
) 
 104     wxLogTrace(wxTrace_Timer
, wxT("Removing timer %d"), timer
->GetId()); 
 106     for ( wxTimerList::iterator node 
= m_timers
.begin(); 
 107           node 
!= m_timers
.end(); 
 110         if ( (*node
)->m_timer 
== timer 
) 
 113             m_timers
.erase(node
); 
 118     wxFAIL_MSG( wxT("removing inexistent timer?") ); 
 121 bool wxTimerScheduler::GetNext(wxUsecClock_t 
*remaining
) const 
 123     if ( m_timers
.empty() ) 
 126     wxCHECK_MSG( remaining
, false, wxT("NULL pointer") ); 
 128     *remaining 
= (*m_timers
.begin())->m_expiration 
- wxGetLocalTimeUsec(); 
 129     if ( *remaining 
< 0 ) 
 131         // timer already expired, don't wait at all before notifying it 
 138 bool wxTimerScheduler::NotifyExpired() 
 140     if ( m_timers
.empty() ) 
 143     const wxUsecClock_t now 
= wxGetLocalTimeUsec(); 
 145     typedef wxVector
<wxUnixTimerImpl 
*> TimerImpls
; 
 147     for ( wxTimerList::iterator next
, 
 148             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         // we can't notify the timer from this loop as the timer event handler 
 186         // could modify m_timers (for example, but not only, by stopping this 
 187         // timer) which would render our iterators invalid, so do it after the 
 189         toNotify
.push_back(timer
); 
 192     if ( toNotify
.empty() ) 
 195     for ( TimerImpls::const_iterator i 
= toNotify
.begin(), 
 196                                      end 
= toNotify
.end(); 
 206 // ============================================================================ 
 207 // wxUnixTimerImpl implementation 
 208 // ============================================================================ 
 210 wxUnixTimerImpl::wxUnixTimerImpl(wxTimer
* timer
) 
 216 bool wxUnixTimerImpl::Start(int milliseconds
, bool oneShot
) 
 218     // notice that this will stop an already running timer 
 219     wxTimerImpl::Start(milliseconds
, oneShot
); 
 221     wxTimerScheduler::Get().AddTimer(this, wxGetLocalTimeUsec() + m_milli
*1000); 
 227 void wxUnixTimerImpl::Stop() 
 231         wxTimerScheduler::Get().RemoveTimer(this); 
 237 bool wxUnixTimerImpl::IsRunning() const 
 242 wxUnixTimerImpl::~wxUnixTimerImpl() 
 244     wxASSERT_MSG( !m_isRunning
, wxT("must have been stopped before") ); 
 247 // ============================================================================ 
 248 // wxTimerUnixModule: responsible for freeing the global timer scheduler 
 249 // ============================================================================ 
 251 class wxTimerUnixModule 
: public wxModule
 
 254     wxTimerUnixModule() {} 
 255     virtual bool OnInit() { return true; } 
 256     virtual void OnExit() { wxTimerScheduler::Shutdown(); } 
 258     DECLARE_DYNAMIC_CLASS(wxTimerUnixModule
) 
 261 IMPLEMENT_DYNAMIC_CLASS(wxTimerUnixModule
, wxModule
) 
 263 // ============================================================================ 
 265 // ============================================================================ 
 267 wxUsecClock_t 
wxGetLocalTimeUsec() 
 269 #ifdef HAVE_GETTIMEOFDAY 
 271     if ( wxGetTimeOfDay(&tv
) != -1 ) 
 273         wxUsecClock_t val 
= 1000000L; // usec/sec 
 275         return val 
+ tv
.tv_usec
; 
 277 #endif // HAVE_GETTIMEOFDAY 
 279     return wxGetLocalTimeMillis() * 1000L; 
 282 wxTimerImpl 
*wxConsoleAppTraits::CreateTimerImpl(wxTimer 
*timer
) 
 284     return new wxUnixTimerImpl(timer
); 
 287 #endif // wxUSE_TIMER