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

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

.

File size: 10.1 KB
Line 
1/* $Id: os2timer.cpp,v 1.10 1999-08-31 15:47:48 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 minimum 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 iMin = -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 < iMin) // determine minimum time period
193 iMin = timeRes->dwPeriod;
194 }
195
196 return iMin;
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: logic sux ... waits for creation of semaphores
223 DosSleep(100);
224}
225/******************************************************************************/
226/******************************************************************************/
227OS2Timer::~OS2Timer()
228{
229 OS2Timer *timer = OS2Timer::timers;
230
231 KillTimer();
232
233 if(timer != this)
234 {
235 while(timer->next != this)
236 {
237 timer = timer->next;
238 }
239 timer->next = this->next;
240 }
241 else
242 timers = timer->next;
243}
244/******************************************************************************/
245/******************************************************************************/
246BOOL OS2Timer::StartTimer(int period,
247 int resolution,
248 LPTIMECALLBACK lptc,
249 int dwUser,
250 int fuEvent)
251{
252 APIRET rc;
253
254 if(TimerThreadID == -1)
255 {
256 return(FALSE);
257 }
258
259 if(TimerStatus == Stopped)
260 {
261 clientCallback = lptc;
262 userData = dwUser;
263
264 if(fuEvent == TIME_PERIODIC)
265 rc = DosStartTimer(period, (HSEM)TimerSem, &TimerHandle);
266 else
267 rc = DosAsyncTimer(period, (HSEM)TimerSem, &TimerHandle);
268
269 if(rc)
270 {
271
272#ifdef DEBUG
273 if(fuEvent == TIME_PERIODIC)
274 WriteLog("DosStartTimer failed %d\n", rc);
275 else
276 WriteLog("DosAsyncTimer failed %d\n", rc);
277#endif
278
279 return(FALSE);
280 }
281
282 TimerStatus = Running;
283 }
284 else
285 return(FALSE); //already running (must use timeKillEvent first)
286
287 return(TRUE);
288}
289/******************************************************************************/
290/******************************************************************************/
291void OS2Timer::StopTimer()
292{
293 if(TimerStatus == Running)
294 {
295 DosStopTimer(TimerHandle);
296 TimerStatus = Stopped;
297 }
298}
299/******************************************************************************/
300/******************************************************************************/
301void OS2Timer::KillTimer()
302{
303 fFatal = TRUE;
304 DosStopTimer(TimerHandle);
305 if(DosPostEventSem(TimerSem))
306 { //something went wrong
307 DosKillThread(TimerThreadID);
308 DosCloseEventSem(TimerSem);
309 }
310 TimerStatus = InActive;
311}
312/******************************************************************************/
313//******************************************************************************
314void OS2Timer::TimerHandler()
315{
316 ULONG Count = 0;
317 APIRET rc = 0; /* Return code */
318 USHORT selTIB;
319
320 dprintf(("WINMM: TimerHandler thread created\n"));
321
322 rc = DosSetPriority (PRTYS_THREAD, /* Change a single thread */
323 PRTYC_TIMECRITICAL, /* Time critical class */
324 0L, /* Increase by 15 */
325 0L); /* Assume current thread */
326
327 rc = DosCreateEventSem(NULL, &TimerSem, DC_SEM_SHARED, 0);
328 if(rc != 0)
329 {
330 dprintf(("WINMM: OS2Timer: DosCreateEventSem failed rc=#%08xh\n", rc));
331 _endthread();
332 }
333
334 TimerStatus = Stopped;
335
336 while(!fFatal)
337 {
338 DosWaitEventSem(TimerSem, SEM_INDEFINITE_WAIT);
339 DosResetEventSem(TimerSem, &Count);
340 if(!fFatal)
341 {
342 // @@@PH: we're calling the client with PRTYC_TIMECRITICAL !!!
343 // It'd be much nicer to call with original priority!
344
345 selTIB = SetWin32TIB();
346 clientCallback((UINT)this, 0, userData, 0, 0);
347 SetFS(selTIB);
348 }
349 }
350 DosCloseEventSem(TimerSem);
351}
352//******************************************************************************
353//******************************************************************************
354static void _Optlink TimerHlpHandler(void *timer)
355{
356 ((OS2Timer *)timer)->TimerHandler();
357
358 _endthread();
359}
360
361
362//******************************************************************************
363//******************************************************************************
364OS2TimerResolution *OS2TimerResolution::sTimerResolutions = NULL;
365OS2Timer *OS2Timer::timers = NULL;
366int OS2Timer::timerPeriod = 0;
367
Note: See TracBrowser for help on using the repository browser.