source: trunk/src/winmm/os2timer.cpp@ 756

Last change on this file since 756 was 756, checked in by phaller, 26 years ago

Add: added timeBeginPeriod and timeEndPeriod

File size: 10.1 KB
Line 
1/* $Id: os2timer.cpp,v 1.8 1999-08-31 15:04:10 phaller Exp $ */
2
3/*
4 * OS/2 Timer class
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 * Copyright 1999 Patrick Haller (phaller@gmx.net)
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13
14/****************************************************************************
15 * Includes *
16 ****************************************************************************/
17
18#define INCL_DOSPROCESS
19#define INCL_DOSDATETIME
20#define INCL_DOSSEMAPHORES
21#include <os2wrap.h> //Odin32 OS/2 api wrappers
22#include <process.h>
23#include <win32type.h>
24#include <wprocess.h>
25#include <misc.h>
26
27#include "time.h"
28#include "os2timer.h"
29
30
31
32/****************************************************************************
33 * Structures *
34 ****************************************************************************/
35
36
37/****************************************************************************
38 * Local Prototypes *
39 ****************************************************************************/
40
41static void _Optlink TimerHlpHandler(void *);
42
43
44
45
46/****************************************************************************
47 * Class: OS2TimerResolution *
48 ****************************************************************************/
49
50
51/*****************************************************************************
52 * Name : OS2TimerResolution::OS2TimerResolution
53 * Purpose : create a new entry in the resolution stack
54 * Parameters: -
55 * Variables :
56 * Result :
57 * Remark :
58 * Status : UNTESTED STUB
59 *
60 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
61 *****************************************************************************/
62
63OS2TimerResolution::OS2TimerResolution(int dwPeriod)
64{
65 // add to linked list
66 OS2TimerResolution *timeRes = OS2TimerResolution::sTimerResolutions;
67
68 if(timeRes != NULL)
69 {
70 while(timeRes->next != NULL)
71 {
72 timeRes = timeRes->next;
73 }
74 timeRes->next = this;
75 }
76 else
77 OS2TimerResolution::sTimerResolutions = this;
78
79 this->dwPeriod = dwPeriod;
80}
81
82
83/*****************************************************************************
84 * Name : OS2TimerResolution::~OS2TimerResolution
85 * Purpose : remove entry from the linked list
86 * Parameters:
87 * Variables :
88 * Result :
89 * Remark :
90 * Status : UNTESTED STUB
91 *
92 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
93 *****************************************************************************/
94
95OS2TimerResolution::~OS2TimerResolution()
96{
97 // remove from linked list
98 OS2TimerResolution *timeRes = OS2TimerResolution::sTimerResolutions;
99
100 // leaveResolutionScope() if still entered???
101
102 if(timeRes != this)
103 {
104 while(timeRes->next != this)
105 {
106 timeRes = timeRes->next;
107 }
108 timeRes->next = this->next;
109 }
110 else
111 OS2TimerResolution::sTimerResolutions = timeRes->next;
112}
113
114
115/*****************************************************************************
116 * Name : OS2TimerResolution::enterResolutionScope
117 * Purpose : set the currently requested timer resolution for this entry
118 * Parameters:
119 * Variables :
120 * Result :
121 * Remark :
122 * Status : UNTESTED STUB
123 *
124 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
125 *****************************************************************************/
126
127BOOL OS2TimerResolution::enterResolutionScope(int dwPeriod)
128{
129 OS2TimerResolution* timeRes = new OS2TimerResolution(dwPeriod);
130 if (timeRes != NULL)
131 return TRUE;
132 else
133 return FALSE;
134}
135
136
137/*****************************************************************************
138 * Name : OS2TimerResolution::leaveResolutionScope
139 * Purpose : remove specified entry from the list if periods match
140 * Parameters: int dwPeriod
141 * Variables :
142 * Result : TRUE or FALSE
143 * Remark :
144 * Status : UNTESTED STUB
145 *
146 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
147 *****************************************************************************/
148
149BOOL OS2TimerResolution::leaveResolutionScope(int dwPeriod)
150{
151 OS2TimerResolution* timeRes = OS2TimerResolution::sTimerResolutions;
152
153 if (timeRes != NULL)
154 {
155 for(; // walk to the end of the list
156 timeRes->next != NULL;
157 timeRes = timeRes->next)
158 ;
159
160 if (timeRes->dwPeriod == dwPeriod) // do the requested period match?
161 {
162 delete timeRes; // so delete that object
163 return TRUE; // OK, can remove the entry
164 }
165 }
166 return FALSE; // nope, mismatch !
167}
168
169
170/*****************************************************************************
171 * Name : OS2TimerResolution::queryCurrentResolution
172 * Purpose : determine the maximum resolution currently requested
173 * Parameters:
174 * Variables :
175 * Result :
176 * Remark :
177 * Status : UNTESTED STUB
178 *
179 * Author : Patrick Haller [Tue, 1998/06/16 23:00]
180 *****************************************************************************/
181
182int OS2TimerResolution::queryCurrentResolution()
183{
184 OS2TimerResolution *timeRes = OS2TimerResolution::sTimerResolutions;
185 int iMax = -1;
186
187 if (timeRes != NULL) // do we have an entry yet?
188 for (; // walk the linked list
189 timeRes->next != NULL;
190 timeRes = timeRes->next)
191 {
192 if (timeRes->dwPeriod < iMax) // determine minimum time period
193 iMax = timeRes->dwPeriod;
194 }
195
196 return iMax;
197}
198
199
200
201
202
203/******************************************************************************/
204/******************************************************************************/
205OS2Timer::OS2Timer() : TimerSem(0), TimerHandle(0), TimerThreadID(0),
206 clientCallback(NULL), TimerStatus(Stopped), fFatal(FALSE)
207{
208 OS2Timer *timer = OS2Timer::timers;
209
210 if(timer != NULL)
211 {
212 while(timer->next != NULL)
213 {
214 timer = timer->next;
215 }
216 timer->next = this;
217 }
218 else
219 timers = this;
220
221 TimerThreadID = _beginthread(TimerHlpHandler, NULL, 0x4000, (void *)this);
222 //@@@PH: why the wait? DosSleep(100);
223}
224/******************************************************************************/
225/******************************************************************************/
226OS2Timer::~OS2Timer()
227{
228 OS2Timer *timer = OS2Timer::timers;
229
230 KillTimer();
231
232 if(timer != this)
233 {
234 while(timer->next != this)
235 {
236 timer = timer->next;
237 }
238 timer->next = this->next;
239 }
240 else
241 timers = timer->next;
242}
243/******************************************************************************/
244/******************************************************************************/
245BOOL OS2Timer::StartTimer(int period,
246 int resolution,
247 LPTIMECALLBACK lptc,
248 int dwUser,
249 int fuEvent)
250{
251 APIRET rc;
252
253 if(TimerThreadID == -1)
254 {
255 return(FALSE);
256 }
257
258 if(TimerStatus == Stopped)
259 {
260 clientCallback = lptc;
261 userData = dwUser;
262
263 if(fuEvent == TIME_PERIODIC)
264 rc = DosStartTimer(period, (HSEM)TimerSem, &TimerHandle);
265 else
266 rc = DosAsyncTimer(period, (HSEM)TimerSem, &TimerHandle);
267
268 if(rc)
269 {
270
271#ifdef DEBUG
272 if(fuEvent == TIME_PERIODIC)
273 WriteLog("DosStartTimer failed %d\n", rc);
274 else
275 WriteLog("DosAsyncTimer failed %d\n", rc);
276#endif
277
278 return(FALSE);
279 }
280
281 TimerStatus = Running;
282 }
283 else
284 return(FALSE); //already running (must use timeKillEvent first)
285
286 return(TRUE);
287}
288/******************************************************************************/
289/******************************************************************************/
290void OS2Timer::StopTimer()
291{
292 if(TimerStatus == Running)
293 {
294 DosStopTimer(TimerHandle);
295 TimerStatus = Stopped;
296 }
297}
298/******************************************************************************/
299/******************************************************************************/
300void OS2Timer::KillTimer()
301{
302 fFatal = TRUE;
303 DosStopTimer(TimerHandle);
304 if(DosPostEventSem(TimerSem))
305 { //something went wrong
306 DosKillThread(TimerThreadID);
307 DosCloseEventSem(TimerSem);
308 }
309 TimerStatus = InActive;
310}
311/******************************************************************************/
312//******************************************************************************
313void OS2Timer::TimerHandler()
314{
315 ULONG Count = 0;
316 APIRET rc = 0; /* Return code */
317 USHORT selTIB;
318
319 dprintf(("WINMM: TimerHandler thread created\n"));
320
321 rc = DosSetPriority (PRTYS_THREAD, /* Change a single thread */
322 PRTYC_TIMECRITICAL, /* Time critical class */
323 0L, /* Increase by 15 */
324 0L); /* Assume current thread */
325
326 rc = DosCreateEventSem(NULL, &TimerSem, DC_SEM_SHARED, 0);
327
328 if(rc != 0)
329 _endthread();
330
331 dprintf(("WINMM: OS2Timer:Semaphore created\n"));
332
333 TimerStatus = Stopped;
334
335 while(!fFatal)
336 {
337 DosWaitEventSem(TimerSem, SEM_INDEFINITE_WAIT);
338 DosResetEventSem(TimerSem, &Count);
339 if(!fFatal)
340 {
341 // @@@PH: we're calling the client with PRTYC_TIMECRITICAL !!!
342 // It'd be much nicer to call with original priority!
343
344 selTIB = SetWin32TIB();
345 clientCallback((UINT)this, 0, userData, 0, 0);
346 SetFS(selTIB);
347 }
348 }
349 DosCloseEventSem(TimerSem);
350}
351//******************************************************************************
352//******************************************************************************
353static void _Optlink TimerHlpHandler(void *timer)
354{
355 ((OS2Timer *)timer)->TimerHandler();
356
357 _endthread();
358}
359
360
361//******************************************************************************
362//******************************************************************************
363OS2TimerResolution *OS2TimerResolution::sTimerResolutions = NULL;
364OS2Timer *OS2Timer::timers = NULL;
365int OS2Timer::timerPeriod = 0;
366
Note: See TracBrowser for help on using the repository browser.