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

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

Fix: started reimplementation of OS2Timer

File size: 6.6 KB
Line 
1/* $Id: os2timer.cpp,v 1.6 1999-08-24 16:12:04 phaller Exp $ */
2
3/*
4 * OS/2 Timer class
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 */
11
12
13/****************************************************************************
14 * Includes *
15 ****************************************************************************/
16
17#define INCL_DOSPROCESS
18#define INCL_DOSDATETIME
19#define INCL_DOSSEMAPHORES
20#include <os2wrap.h> //Odin32 OS/2 api wrappers
21#include <process.h>
22#include "win32type.h"
23#include "wintimer.h"
24#include "os2timer.h"
25#include "misc.h"
26
27
28
29/****************************************************************************
30 * Structures *
31 ****************************************************************************/
32
33#if 0
34//@@@PH started new implementation
35typedef struct _MMTIMEREVENT
36{
37 struct _MMTIMEREVENT* prev;
38 struct _MMTIMEREVENT* next;
39
40 DWORD id; // event id
41 DWORD timeScheduled; // system time to fire event
42 DWORD timePeriod; // period if periodic event
43 TID tidCaller; // thread ID of caller thread
44 DWORD dwUser; // user supplied value
45 LPTIMERCALLBACK lpCallback; // address to call
46 DWORD dwFlags; // event flags
47} MMTIMEREVENT, *PMMTIMEREVENT, *LPTIMEREVENT;
48
49typedef struct _MMTIMERRESOLUTION
50{
51 struct _MMTIMERRESOLUTION* prev;
52 struct _MMTIMERRESOLUTION* next;
53
54 DWORD dwResolution; // requested resolution for block
55} MMTIMERRESOLUTION, *PMMTIMERRESOLUTION, *LPMMTIMERRESOLUTION;
56
57/*
58 enterResolutionScope
59 leaveResolutionScope
60
61 addEvent
62 removeEvent
63 rescheduleEvent
64 callbackCaller
65*/
66#endif
67
68/****************************************************************************
69 * Local Prototypes *
70 ****************************************************************************/
71
72static void _Optlink TimerHlpHandler(void *);
73
74
75
76
77/******************************************************************************/
78/******************************************************************************/
79OS2Timer::OS2Timer() : TimerSem(0), TimerHandle(0), TimerThreadID(0),
80 clientCallback(NULL), TimerStatus(Stopped), fFatal(FALSE)
81{
82 OS2Timer *timer = OS2Timer::timers;
83
84 if(timer != NULL) {
85 while(timer->next != NULL) {
86 timer = timer->next;
87 }
88 timer->next = this;
89 }
90 else timers = this;
91
92 TimerThreadID = _beginthread(TimerHlpHandler, NULL, 0x4000, (void *)this);
93 DosSleep(100);
94}
95/******************************************************************************/
96/******************************************************************************/
97OS2Timer::~OS2Timer()
98{
99 OS2Timer *timer = OS2Timer::timers;
100
101 KillTimer();
102
103 if(timer != this) {
104 while(timer->next != this) {
105 timer = timer->next;
106 }
107 timer->next = this->next;
108 }
109 else timers = timer->next;
110}
111/******************************************************************************/
112/******************************************************************************/
113BOOL OS2Timer::StartTimer(int period, int resolution, LPTIMECALLBACK lptc,
114 int dwUser, int fuEvent)
115{
116 APIRET rc;
117
118 if(TimerThreadID == -1) {
119 return(FALSE);
120 }
121 if(TimerStatus == Stopped) {
122 clientCallback = lptc;
123 userData = dwUser;
124 if(fuEvent == TIME_PERIODIC)
125 rc = DosStartTimer(period, (HSEM)TimerSem, &TimerHandle);
126 else rc = DosAsyncTimer(period, (HSEM)TimerSem, &TimerHandle);
127 if(rc) {
128#ifdef DEBUG
129 if(fuEvent == TIME_PERIODIC)
130 WriteLog("DosStartTimer failed %d\n", rc);
131 else WriteLog("DosAsyncTimer failed %d\n", rc);
132#endif
133 return(FALSE);
134 }
135 TimerStatus = Running;
136 }
137 else return(FALSE); //already running (must use timeKillEvent first)
138 return(TRUE);
139}
140/******************************************************************************/
141/******************************************************************************/
142void OS2Timer::StopTimer()
143{
144 if(TimerStatus == Running) {
145 DosStopTimer(TimerHandle);
146 TimerStatus = Stopped;
147 }
148}
149/******************************************************************************/
150/******************************************************************************/
151void OS2Timer::KillTimer()
152{
153 fFatal = TRUE;
154 DosStopTimer(TimerHandle);
155 if(DosPostEventSem(TimerSem)) {//something went wrong
156 DosKillThread(TimerThreadID);
157 DosCloseEventSem(TimerSem);
158 }
159 TimerStatus = InActive;
160}
161/******************************************************************************/
162//******************************************************************************
163void OS2Timer::TimerHandler()
164{
165 ULONG Count = 0;
166 APIRET rc = 0; /* Return code */
167
168#ifdef DEBUG
169 WriteLog("TimerHandler thread created\n");
170#endif
171 rc = DosSetPriority (PRTYS_THREAD, /* Change a single thread */
172 PRTYC_TIMECRITICAL, /* Time critical class */
173 0L, /* Increase by 15 */
174 0L); /* Assume current thread */
175
176 rc = DosCreateEventSem(NULL, &TimerSem, DC_SEM_SHARED, 0);
177
178 if(rc != 0)
179 _endthread();
180
181#ifdef DEBUG
182 WriteLog("Semaphore created\n");
183#endif
184 TimerStatus = Stopped;
185
186 while(!fFatal) {
187 DosWaitEventSem(TimerSem, SEM_INDEFINITE_WAIT);
188 DosResetEventSem(TimerSem, &Count);
189 if(!fFatal) {
190#ifdef DEBUG
191//// WriteLog("T");
192#endif
193 // @@@PH: we're calling the client with PRTYC_TIMECRITICAL !!!
194 // It'd be much nicer to call with original priority!
195 // @@@PH: plus the original thread is supposed to stop while the
196 // time event is scheduled (DosSuspendThread()) ? It's
197 // much like raising a signal (SIGALARM)
198 clientCallback((UINT)this, 0, userData, 0, 0);
199 }
200 }
201 DosCloseEventSem(TimerSem);
202}
203//******************************************************************************
204//******************************************************************************
205static void _Optlink TimerHlpHandler(void *timer)
206{
207 ((OS2Timer *)timer)->TimerHandler();
208
209 _endthread();
210}
211//******************************************************************************
212//******************************************************************************
213OS2Timer *OS2Timer::timers = NULL;
214int OS2Timer::timerPeriod = 0;
215
Note: See TracBrowser for help on using the repository browser.