]> git.saurik.com Git - wxWidgets.git/blob - src/x11/timer.cpp
More X11 code
[wxWidgets.git] / src / x11 / timer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: x11/timer.cpp
3 // Purpose: wxTimer implementation
4 // Author: Vaclav Slavik
5 // Id: $Id$
6 // Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com)
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10
11 #ifdef __GNUG__
12 #pragma implementation "timer.h"
13 #endif
14
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
17
18 #ifdef __BORLANDC__
19 #pragma hdrstop
20 #endif
21
22 #include "wx/timer.h"
23
24 #if wxUSE_TIMER
25
26 #include "wx/log.h"
27 #include "wx/module.h"
28 #include "wx/x11/private.h"
29
30 // ----------------------------------------------------------------------------
31 // helper structures and wxTimerScheduler
32 // ----------------------------------------------------------------------------
33
34 class wxTimerDesc
35 {
36 public:
37 wxTimerDesc(wxTimer *t) :
38 timer(t), running(FALSE), next(NULL), prev(NULL),
39 shotTime(0), deleteFlag(NULL) {}
40
41 wxTimer *timer;
42 bool running;
43 wxTimerDesc *next, *prev;
44 unsigned long shotTime;
45 volatile bool *deleteFlag; // see comment in ~wxTimer
46 };
47
48 class wxTimerScheduler
49 {
50 public:
51 wxTimerScheduler() : m_timers(NULL) {}
52
53 void QueueTimer(wxTimerDesc *desc, unsigned long when = 0);
54 void RemoveTimer(wxTimerDesc *desc);
55 void NotifyTimers();
56
57 private:
58 wxTimerDesc *m_timers;
59 };
60
61 void wxTimerScheduler::QueueTimer(wxTimerDesc *desc, unsigned long when)
62 {
63 if ( desc->running )
64 return; // already scheduled
65
66 if ( when == 0 )
67 when = wxGetLocalTimeMillis() + desc->timer->GetInterval();
68 desc->shotTime = when;
69 desc->running = TRUE;
70
71 wxLogTrace("mgl_timer", "queued timer %p at tick %i",
72 desc->timer, when);
73
74 if ( m_timers )
75 {
76 wxTimerDesc *d = m_timers;
77 while ( d->next && d->next->shotTime < when ) d = d->next;
78 desc->next = d->next;
79 desc->prev = d;
80 if ( d->next )
81 d->next->prev = desc;
82 d->next = desc;
83 }
84 else
85 {
86 m_timers = desc;
87 desc->prev = desc->next = NULL;
88 }
89 }
90
91 void wxTimerScheduler::RemoveTimer(wxTimerDesc *desc)
92 {
93 desc->running = FALSE;
94 if ( desc == m_timers )
95 m_timers = desc->next;
96 if ( desc->prev )
97 desc->prev->next = desc->next;
98 if ( desc->next )
99 desc->next->prev = desc->prev;
100 desc->prev = desc->next = NULL;
101 }
102
103 void wxTimerScheduler::NotifyTimers()
104 {
105 if ( m_timers )
106 {
107 bool oneShot;
108 volatile bool timerDeleted;
109 unsigned long now = wxGetLocalTimeMillis();
110 wxTimerDesc *desc;
111
112 while ( m_timers && m_timers->shotTime <= now )
113 {
114 desc = m_timers;
115 oneShot = desc->timer->IsOneShot();
116 RemoveTimer(desc);
117
118 timerDeleted = FALSE;
119 desc->deleteFlag = &timerDeleted;
120 desc->timer->Notify();
121
122 if ( !timerDeleted )
123 {
124 wxLogTrace("mgl_timer", "notified timer %p sheduled for %i",
125 desc->timer, desc->shotTime);
126
127 desc->deleteFlag = NULL;
128 if ( !oneShot )
129 QueueTimer(desc, now + desc->timer->GetInterval());
130 }
131 }
132 }
133 }
134
135
136
137 // ----------------------------------------------------------------------------
138 // wxTimer
139 // ----------------------------------------------------------------------------
140
141 IMPLEMENT_ABSTRACT_CLASS(wxTimer,wxObject)
142
143 wxTimerScheduler *gs_scheduler = NULL;
144
145 void wxTimer::Init()
146 {
147 if ( !gs_scheduler )
148 gs_scheduler = new wxTimerScheduler;
149 m_desc = new wxTimerDesc(this);
150 }
151
152 wxTimer::~wxTimer()
153 {
154 wxLogTrace("mgl_timer", "destroying timer %p...", this);
155 if ( IsRunning() )
156 Stop();
157
158 // NB: this is a hack: wxTimerScheduler must have some way of knowing
159 // that wxTimer object was deleted under its hands -- this may
160 // happen if somebody is really nasty and deletes the timer
161 // from wxTimer::Notify()
162 if ( m_desc->deleteFlag != NULL )
163 *m_desc->deleteFlag = TRUE;
164
165 delete m_desc;
166 wxLogTrace("mgl_timer", " ...done destroying timer %p...", this);
167 }
168
169 bool wxTimer::IsRunning() const
170 {
171 return m_desc->running;
172 }
173
174 bool wxTimer::Start(int millisecs, bool oneShot)
175 {
176 wxLogTrace("mgl_timer", "started timer %p: %i ms, oneshot=%i",
177 this, millisecs, oneShot);
178
179 if ( !wxTimerBase::Start(millisecs, oneShot) )
180 return FALSE;
181
182 gs_scheduler->QueueTimer(m_desc);
183 return TRUE;
184 }
185
186 void wxTimer::Stop()
187 {
188 if ( !m_desc->running ) return;
189
190 gs_scheduler->RemoveTimer(m_desc);
191 }
192
193 /*static*/ void wxTimer::NotifyTimers()
194 {
195 if ( gs_scheduler )
196 gs_scheduler->NotifyTimers();
197 }
198
199
200
201 // A module to deallocate memory properly:
202 class wxTimerModule: public wxModule
203 {
204 DECLARE_DYNAMIC_CLASS(wxTimerModule)
205 public:
206 wxTimerModule() {}
207 bool OnInit() { return TRUE; }
208 void OnExit() { delete gs_scheduler; gs_scheduler = NULL; }
209 };
210
211 IMPLEMENT_DYNAMIC_CLASS(wxTimerModule, wxModule)
212
213
214 #endif //wxUSE_TIMER