]>
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