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