- Timestamp:
- Mar 8, 2001, 8:28:45 PM (24 years ago)
- Location:
- trunk/src/helpers
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/procstat.c
r14 r44 114 114 VOID prc16FreeInfo(PQPROCSTAT16 pInfo) 115 115 { 116 free(pInfo); 116 if (pInfo) 117 free(pInfo); 117 118 } 118 119 … … 133 134 PQPROCESS16 pProcess, 134 135 pReturn = NULL; 135 for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0); 136 pProcess->ulType != 3; 137 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList, 138 pProcess->usThreads * sizeof(QTHREAD16)) 139 ) 140 { 141 CHAR szModuleName[CCHMAXPATH]; 142 if (DosQueryModuleName(pProcess->usHModule, 143 sizeof(szModuleName), 144 szModuleName) 145 == NO_ERROR) 146 { 147 // the module name is fully qualified, so find the 148 // file name (after the last backslash) 149 PSZ pLastBackslash = strrchr(szModuleName, '\\'); 150 if (pLastBackslash) 151 // found: 152 if (stricmp(pLastBackslash + 1, pcszName) == 0) 153 { 154 // matches: 155 pReturn = pProcess; 156 break; 157 } 136 if (pInfo) 137 { 138 for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0); 139 pProcess->ulType != 3; 140 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList, 141 pProcess->usThreads * sizeof(QTHREAD16)) 142 ) 143 { 144 CHAR szModuleName[CCHMAXPATH]; 145 if (DosQueryModuleName(pProcess->usHModule, 146 sizeof(szModuleName), 147 szModuleName) 148 == NO_ERROR) 149 { 150 // the module name is fully qualified, so find the 151 // file name (after the last backslash) 152 PSZ pLastBackslash = strrchr(szModuleName, '\\'); 153 if (pLastBackslash) 154 // found: 155 if (stricmp(pLastBackslash + 1, pcszName) == 0) 156 { 157 // matches: 158 pReturn = pProcess; 159 break; 160 } 161 } 158 162 } 159 163 } … … 178 182 PQPROCESS16 pProcess, 179 183 pReturn = NULL; 180 for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0); 181 pProcess->ulType != 3; 182 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList, 183 pProcess->usThreads * sizeof(QTHREAD16)) 184 ) 185 { 186 if (pProcess->usPID == ulPID) 187 { 188 pReturn = pProcess; 189 break; 184 if (pInfo) 185 { 186 for ( pProcess = (PQPROCESS16)PTR(pInfo->ulProcesses, 0); 187 pProcess->ulType != 3; 188 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList, 189 pProcess->usThreads * sizeof(QTHREAD16)) 190 ) 191 { 192 if (pProcess->usPID == ulPID) 193 { 194 pReturn = pProcess; 195 break; 196 } 190 197 } 191 198 } … … 207 214 VOID prcReport16(PQPROCESS16 pProcess, PPRCPROCESS pprcp) 208 215 { 209 // USHORT usPriority = 0; 210 PQTHREAD16 pThread; 211 int i; 212 213 DosQueryModuleName(pProcess->usHModule, 214 sizeof(pprcp->szModuleName), 215 pprcp->szModuleName); 216 // DosGetPrty(PRTYS_PROCESS, &(pprcp->usPriority), pProcess->usPID); 217 218 // sum up CPU time for process 219 for (pprcp->ulCPU = 0, 220 i = 0, 221 pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0); 222 i < pProcess->usThreads; 223 i++, pThread++ ) 224 { 225 pprcp->ulCPU += (pThread->ulSysTime + pThread->ulUserTime); 226 } 227 228 pprcp->usPID = pProcess->usPID; 229 pprcp->usParentPID = pProcess->usParentPID; 230 pprcp->usThreads = pProcess->usThreads; 231 pprcp->ulSID = pProcess->ulSID; 232 pprcp->ulSessionType = pProcess->ulSessionType; 233 pprcp->ulStatus = pProcess->ulStatus; 216 if (pProcess) 217 { 218 PQTHREAD16 pThread; 219 int i; 220 221 DosQueryModuleName(pProcess->usHModule, 222 sizeof(pprcp->szModuleName), 223 pprcp->szModuleName); 224 // DosGetPrty(PRTYS_PROCESS, &(pprcp->usPriority), pProcess->usPID); 225 226 // sum up CPU time for process 227 for (pprcp->ulCPU = 0, 228 i = 0, 229 pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0); 230 i < pProcess->usThreads; 231 i++, pThread++ ) 232 { 233 pprcp->ulCPU += (pThread->ulSysTime + pThread->ulUserTime); 234 } 235 236 pprcp->usPID = pProcess->usPID; 237 pprcp->usParentPID = pProcess->usParentPID; 238 pprcp->usThreads = pProcess->usThreads; 239 pprcp->ulSID = pProcess->ulSID; 240 pprcp->ulSessionType = pProcess->ulSessionType; 241 pprcp->ulStatus = pProcess->ulStatus; 242 } 234 243 } 235 244 … … 243 252 */ 244 253 245 BOOL prc16QueryProcessInfo(USHORT usPID, // in: PID to query 246 PPRCPROCESS pprcp) // out: process info 254 BOOL prc16QueryProcessInfo(PQPROCSTAT16 pps, // in: from prc16GetInfo 255 USHORT usPID, // in: PID to query 256 PPRCPROCESS pprcp) // out: process info 247 257 { 248 258 BOOL rc = FALSE; 249 PQPROCESS16 pProcess;250 PQPROCSTAT16 pps = (PQPROCSTAT16)malloc(0x8000);251 DosQProcStatus(pps, 0x8000);252 253 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0);254 pProcess->ulType != 3;255 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList,256 pProcess->usThreads * sizeof(QTHREAD16))257 )258 {259 if (pProcess->usPID == usPID)260 {261 prcReport16(pProcess, pprcp);262 rc = TRUE;263 break;264 }265 }266 267 free(pps); 259 if (pps) 260 { 261 PQPROCESS16 pProcess; 262 263 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0); 264 pProcess->ulType != 3; 265 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList, 266 pProcess->usThreads * sizeof(QTHREAD16)) 267 ) 268 { 269 if (pProcess->usPID == usPID) 270 { 271 prcReport16(pProcess, pprcp); 272 rc = TRUE; 273 break; 274 } 275 } 276 } 277 268 278 return (rc); 269 279 } … … 315 325 * in the given process. If pid == 0, the 316 326 * total thread count for the system is returned. 317 */ 318 319 ULONG prc16QueryThreadCount(USHORT usPID) 327 * 328 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param 329 */ 330 331 ULONG prc16QueryThreadCount(PQPROCSTAT16 pps, // in: from prc16GetInfo 332 USHORT usPID) 320 333 { 321 334 ULONG ulrc = 0; 322 PQPROCSTAT16 pps = (PQPROCSTAT16)malloc(0x8000); 323 DosQProcStatus(pps, 0x8000); 324 325 if (usPID) 326 { 327 // process query: 335 336 if (pps) 337 { 338 if (usPID) 339 { 340 // process query: 341 PQPROCESS16 pProcess; 342 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0); 343 pProcess->ulType != 3; 344 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList, 345 pProcess->usThreads * sizeof(QTHREAD16)) 346 ) 347 { 348 if (pProcess->usPID == usPID) 349 { 350 ulrc = pProcess->usThreads; 351 break; 352 } 353 } 354 } 355 else 356 { 357 // global query: 358 PQGLOBAL16 pg; 359 pg = (PQGLOBAL16)PTR(pps->ulGlobal, 0); 360 ulrc = pg->ulThreads; 361 } 362 } 363 364 return (ulrc); 365 } 366 367 /* 368 *@@ prc16QueryThreadInfo: 369 * this searches for a given thread in a given process 370 * and fills a given PRCTHREAD structure with lots of 371 * information about that thread. 372 * 373 * Returns FALSE upon errors. 374 * 375 * Note: This function loops thru all processes which 376 * are currently running and is therefore not terribly 377 * fast. Use economically. 378 * 379 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param 380 */ 381 382 BOOL prc16QueryThreadInfo(PQPROCSTAT16 pps, // in: from prc16GetInfo 383 USHORT usPID, 384 USHORT usTID, 385 PPRCTHREAD pprct) 386 { 387 BOOL brc = FALSE; 388 if (pps) 389 { 328 390 PQPROCESS16 pProcess; 391 392 // find process: 329 393 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0); 330 394 pProcess->ulType != 3; … … 335 399 if (pProcess->usPID == usPID) 336 400 { 337 ulrc = pProcess->usThreads; 338 break; 401 PQTHREAD16 pThread; 402 int i; 403 // process found: find thread 404 for ( i = 0, pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0); 405 i < pProcess->usThreads; 406 i++, pThread++ ) 407 { 408 if (pThread->usTID == usTID) 409 { 410 // thread found: 411 pprct->usTID = pThread->usTID; 412 pprct->usThreadSlotID = pThread->usThreadSlotID; 413 pprct->ulBlockID = pThread->ulBlockID; 414 pprct->ulPriority = pThread->ulPriority; 415 pprct->ulSysTime = pThread->ulSysTime; 416 pprct->ulUserTime = pThread->ulUserTime; 417 pprct->ucStatus = pThread->ucStatus; 418 419 brc = TRUE; 420 421 break; // thread-for loop 422 } 423 } // end for thread 424 break; // process-for loop 339 425 } 340 } 341 } 342 else 343 { 344 // global query: 345 PQGLOBAL16 pg; 346 pg = (PQGLOBAL16)PTR(pps->ulGlobal, 0); 347 ulrc = pg->ulThreads; 348 } 349 350 free(pps); 351 return (ulrc); 352 } 353 354 /* 355 *@@ prc16QueryThreadInfo: 356 * this searches for a given thread in a given process 357 * and fills a given PRCTHREAD structure with lots of 358 * information about that thread. 359 * 360 * Returns FALSE upon errors. 426 } // end for process 427 } 428 429 return (brc); 430 } 431 432 /* 433 *@@ prcQueryPriority: 434 * shortcut to prc16QueryThreadInfo if you want the priority only. 435 * 436 * Returns -1 upon errors. 361 437 * 362 438 * Note: This function loops thru all processes which 363 439 * are currently running and is therefore not terribly 364 440 * fast. Use economically. 365 */ 366 367 BOOL prc16QueryThreadInfo(USHORT usPID, USHORT usTID, PPRCTHREAD pprct) 368 { 369 BOOL brc = FALSE; 370 PQPROCSTAT16 pps = (PQPROCSTAT16)malloc(0x8000); 371 PQPROCESS16 pProcess; 372 DosQProcStatus(pps, 0x8000); 373 374 // find process: 375 for ( pProcess = (PQPROCESS16)PTR(pps->ulProcesses, 0); 376 pProcess->ulType != 3; 377 pProcess = (PQPROCESS16)PTR(pProcess->ulThreadList, 378 pProcess->usThreads * sizeof(QTHREAD16)) 379 ) 380 { 381 if (pProcess->usPID == usPID) 382 { 383 PQTHREAD16 pThread; 384 int i; 385 // process found: find thread 386 for ( i = 0, pThread = (PQTHREAD16)PTR(pProcess->ulThreadList, 0); 387 i < pProcess->usThreads; 388 i++, pThread++ ) 389 { 390 if (pThread->usTID == usTID) 391 { 392 // thread found: 393 pprct->usTID = pThread->usTID; 394 pprct->usThreadSlotID = pThread->usThreadSlotID; 395 pprct->ulBlockID = pThread->ulBlockID; 396 pprct->ulPriority = pThread->ulPriority; 397 pprct->ulSysTime = pThread->ulSysTime; 398 pprct->ulUserTime = pThread->ulUserTime; 399 pprct->ucStatus = pThread->ucStatus; 400 401 brc = TRUE; 402 403 break; // thread-for loop 404 } 405 } // end for thread 406 break; // process-for loop 407 } 408 } // end for process 409 410 free(pps); 411 return (brc); 412 } 413 414 /* 415 *@@ prcQueryPriority: 416 * shortcut to prc16QueryThreadInfo if you want the priority only. 417 * 418 * Returns -1 upon errors. 419 * 420 * Note: This function loops thru all processes which 421 * are currently running and is therefore not terribly 422 * fast. Use economically. 423 */ 424 425 ULONG prc16QueryThreadPriority(USHORT usPID, 441 * 442 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pps param 443 */ 444 445 ULONG prc16QueryThreadPriority(PQPROCSTAT16 pps, // in: from prc16GetInfo 446 USHORT usPID, 426 447 USHORT usTID) 427 448 { 428 449 PRCTHREAD prct; 429 450 ULONG ulrc = -1; 430 if (prc16QueryThreadInfo( usPID, usTID, &prct))451 if (prc16QueryThreadInfo(pps, usPID, usTID, &prct)) 431 452 ulrc = prct.ulPriority; 432 453 return (ulrc); -
trunk/src/helpers/threads.c
r38 r44 50 50 #include "setup.h" // code generation and debugging options 51 51 52 #include "helpers\linklist.h" 52 53 #include "helpers\threads.h" 53 54 … … 58 59 * see threads.c. 59 60 */ 61 62 /* ****************************************************************** 63 * 64 * Global variables 65 * 66 ********************************************************************/ 67 68 LINKLIST G_llThreadInfos; 69 // linked list of all THREADINFOS ever created... 70 // no auto-free 71 HMTX G_hmtxThreadInfos = NULLHANDLE; 72 73 /* ****************************************************************** 74 * 75 * Functions 76 * 77 ********************************************************************/ 78 79 /* 80 *@@ LockThreadInfos: 81 * 82 *@@added V0.9.9 (2001-03-07) [umoeller] 83 */ 84 85 BOOL LockThreadInfos(VOID) 86 { 87 APIRET arc = NO_ERROR; 88 89 if (G_hmtxThreadInfos == NULLHANDLE) 90 { 91 // first call: 92 arc = DosCreateMutexSem(NULL, // unnamed 93 &G_hmtxThreadInfos, 94 0, // unshared 95 TRUE); // request! 96 lstInit(&G_llThreadInfos, FALSE); 97 } 98 else 99 { 100 arc = DosRequestMutexSem(G_hmtxThreadInfos, 101 SEM_INDEFINITE_WAIT); 102 } 103 104 return (arc == NO_ERROR); 105 } 106 107 /* 108 *@@ UnlockThreadInfos: 109 * 110 *@@added V0.9.9 (2001-03-07) [umoeller] 111 */ 112 113 VOID UnlockThreadInfos(VOID) 114 { 115 DosReleaseMutexSem(G_hmtxThreadInfos); 116 } 60 117 61 118 /* … … 108 165 DosCloseEventSem(pti->hevRunning); 109 166 167 // V0.9.9 (2001-03-07) [umoeller] 168 // remove thread from global list 169 if (LockThreadInfos()) 170 { 171 lstRemoveItem(&G_llThreadInfos, pti); 172 UnlockThreadInfos(); 173 } 174 110 175 // (2000-12-18) [lafaix] clean up pti if thread is transient. 111 176 if (pti->flFlags & THRF_TRANSIENT) … … 128 193 /* 129 194 *@@ thrCreate: 130 * this function fills a THREADINFO structure in *pti131 * a nd starts anew thread using _beginthread.195 * this function fills a THREADINFO structure and starts 196 * a new thread using _beginthread. 132 197 * 133 198 * You must pass the thread function in pfn, which will … … 144 209 * function is prototyped somewhere, VAC will automatically 145 210 * modify the function's linkage, and you'll run into 146 * compiler warnings. 147 * 148 * ptiMyself is then a pointer to the THREADINFO structure. 211 * crashes. 212 * 213 * The thread's ptiMyself is then a pointer to the 214 * THREADINFO structure passed to this function. 149 215 * ulData may be obtained like this: 150 + ULONG ulData = ((PTHREADINFO)ptiMyself)->ulData; 216 * 217 + ULONG ulData = ptiMyself->ulData; 218 * 219 * The THREADINFO structure passed to this function must 220 * be accessible all the time while the thread is running 221 * because the thr* functions will use it for maintenance. 222 * 223 * This function does NOT check whether a thread is 224 * already running in *pti. Do not use the same THREADINFO 225 * for several threads. 226 * 227 * If you do not want to manage the structure yourself, 228 * you can pass the THRF_TRANSIENT flag (see below). 151 229 * 152 230 * thrCreate does not call your thread func directly, … … 156 234 * explicitly, because this would skip the exit processing 157 235 * (cleanup) in thr_fntGeneric. Instead, just fall out of 158 * your thread function. 159 * 160 * This function does NOT check whether a thread is 161 * already running in *pti. If it is, that information 162 * will be lost. 236 * your thread function, or return(). 163 237 * 164 238 * flFlags can be any combination of the following: … … 194 268 *@@changed V0.9.7 (2000-12-18) [lafaix]: THRF_TRANSIENT support added 195 269 *@@changed V0.9.9 (2001-02-06) [umoeller]: now returning TID 270 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pcszThreadName 196 271 */ 197 272 … … 200 275 PBOOL pfRunning, // out: variable set to TRUE while thread is running; 201 276 // ptr can be NULL 277 const char *pcszThreadName, // in: thread name (for identification) 202 278 ULONG flFlags, // in: THRF_* flags 203 279 ULONG ulData) // in: user data to be stored in THREADINFO … … 209 285 { 210 286 if (pti == NULL) 211 pti = (PTHREADINFO) malloc(sizeof(THREADINFO)); 287 pti = (PTHREADINFO)malloc(sizeof(THREADINFO)); 288 // cleaned up by thr_fntGeneric on exit 212 289 } 213 290 214 291 if (pti) 215 292 { 216 // we arrive here if *ppti was NULL or (*ppti->tid == NULLHANDLE),217 // i.e. the thread is not already running.218 // _beginthread is contained both in the VAC++ and EMX219 // C libraries with this syntax.220 293 memset(pti, 0, sizeof(THREADINFO)); 221 294 pti->cbStruct = sizeof(THREADINFO); 222 295 pti->pThreadFunc = (PVOID)pfn; 223 296 pti->pfRunning = pfRunning; 297 pti->pcszThreadName = pcszThreadName; // V0.9.9 (2001-03-07) [umoeller] 224 298 pti->flFlags = flFlags; 225 299 pti->ulData = ulData; … … 251 325 252 326 if (ulrc) 327 { 328 if (LockThreadInfos()) 329 { 330 lstAppendItem(&G_llThreadInfos, pti); 331 UnlockThreadInfos(); 332 } 333 253 334 if (flFlags & THRF_WAIT) 254 335 { … … 258 339 SEM_INDEFINITE_WAIT); 259 340 } 341 } 260 342 } 261 343 } … … 281 363 * 282 364 *@@added V0.9.5 (2000-08-26) [umoeller] 365 *@@changed V0.9.9 (2001-03-07) [umoeller]: added pcszThreadName 283 366 */ 284 367 285 368 ULONG thrRunSync(HAB hab, // in: anchor block of calling thread 286 PTHREADFUNC pfn, // in: thread function 287 ULONG ulData) // in: data for thread function 369 PTHREADFUNC pfn, // in: passed to thrCreate 370 const char *pcszThreadName, // in: passed to thrCreate 371 ULONG ulData) // in: passed to thrCreate 288 372 { 289 373 ULONG ulrc = 0; … … 306 390 pfn, 307 391 NULL, 392 pcszThreadName, 308 393 THRF_PMMSGQUEUE, 309 394 ulData); … … 336 421 337 422 return (ulrc); 423 } 424 425 /* 426 *@@ thrListThreads: 427 * returns an array of THREADINFO structures 428 * for all threads that have been started using 429 * thrCreate (or thrRunSync). 430 * 431 * If no threads are running yet, this returns 432 * NULL. 433 * 434 * Otherwise, this returns the pointer to the 435 * first array item, and *pcThreads receives 436 * the array item count (NOT the total array 437 * size). The array is a copied snapshot of all 438 * current THREADINFO's and must be free()'d 439 * by the caller. 440 * 441 *@@added V0.9.9 (2001-03-07) [umoeller] 442 */ 443 444 PTHREADINFO thrListThreads(PULONG pcThreads) 445 { 446 PTHREADINFO pArray = 0; 447 448 if (LockThreadInfos()) 449 { 450 PTHREADINFO pThis; 451 PLISTNODE pNode; 452 *pcThreads = lstCountItems(&G_llThreadInfos); 453 _Pmpf((__FUNCTION__ ": got %d threads", *pcThreads)); 454 pArray = (PTHREADINFO)malloc(*pcThreads * sizeof(THREADINFO)); 455 pThis = pArray; 456 457 pNode = lstQueryFirstNode(&G_llThreadInfos); 458 while (pNode) 459 { 460 memcpy(pThis, 461 (PTHREADINFO)pNode->pItemData, 462 sizeof(THREADINFO)); 463 pThis++; 464 pNode = pNode->pNext; 465 } 466 467 UnlockThreadInfos(); 468 } 469 470 return (pArray); 471 } 472 473 /* 474 *@@ thrFindThread: 475 * attempts to find the thread with the specified 476 * TID; if found, returns TRUE and copies its 477 * THREADINFO into *pti. 478 * 479 *@@added V0.9.9 (2001-03-07) [umoeller] 480 */ 481 482 BOOL thrFindThread(PTHREADINFO pti, 483 ULONG tid) 484 { 485 BOOL brc = FALSE; 486 if (LockThreadInfos()) 487 { 488 PLISTNODE pNode = lstQueryFirstNode(&G_llThreadInfos); 489 while (pNode) 490 { 491 PTHREADINFO ptiThis = (PTHREADINFO)pNode->pItemData; 492 if (ptiThis->tid == tid) 493 { 494 memcpy(pti, ptiThis, sizeof(THREADINFO)); 495 brc = TRUE; 496 break; 497 } 498 pNode = pNode->pNext; 499 } 500 501 UnlockThreadInfos(); 502 } 503 504 return (brc); 338 505 } 339 506 -
trunk/src/helpers/timer.c
r41 r44 5 5 * timer usage. 6 6 * 7 * These timers operate similar to PM timers started 8 * with WinStartTimer. These are implemented thru a 9 * separate thread (fntTimersThread) which posts 10 * WM_TIMER messages regularly. 11 * 12 * Instead of WinStartTimer, use tmrStartXTimer. 13 * Instead of WinStopTimer, use tmrStopXTimer. 7 * The functions here allow you to share a single PM 8 * timer for many windows on the same thread. Basically, 9 * these start a "master PM timer", to whose WM_TIMER 10 * message your window procedure must respond by calling 11 * tmrTimerTick, which will "distribute" the timer tick 12 * to those XTimers which have elapsed. 13 * 14 * So to use XTimers, do the following: 15 * 16 * 1. Create a timer set with tmrCreateSet. Specify 17 * an owner window and the timer ID of the master 18 * PM timer. 19 * 20 * 2. You can then start and stop XTimers for windows 21 * on the same thread by calling tmrStartXTimer and 22 * tmrStopXTimer, respectively. 23 * 24 * 3. In the window proc of the owner window, respond 25 * to WM_TIMER for the master PM timer by calling 26 * tmrTimerTick. This will call the window procs 27 * of those windows with WM_TIMER messages directly 28 * whose XTimers have elapsed. 14 29 * 15 30 * The main advantage of the XTimers is that these … … 27 42 * running. 28 43 * 29 * -- XTimers post WM_TIMER messages regardless of 30 * whether previous WM_TIMER messages have already 31 * been processed. For this reason, be careful with 32 * small timer timeouts, this might flood the 33 * message queue. 44 * -- tmrTimerTick (which you must call when the 45 * "master" WM_TIMER comes in) does not post WM_TIMER 46 * messages to the windows specified in the subtimers, 47 * but calls the window procedure of the target window 48 * directly. This makes sure that timers work even if 49 * some thread is hogging the SIQ. 50 * 51 * This however requires that all XTimers must run on 52 * the same thread as the owner window of the master 53 * timer which was specified with tmrCreateSet. 34 54 * 35 55 * -- Queue timers (with HWND == NULLHANDLE) are not 36 56 * supported. 37 57 * 38 * -- When a window is de leted, its timers are not39 * automatically cleaned up. The timer threaddoes58 * -- When a window is destroyed, its timers are not 59 * automatically cleaned up. tmrTimerTick does 40 60 * detect invalid windows and removes them from the 41 61 * timers list before posting, but to be on the safe … … 106 126 *@@ XTIMER: 107 127 * one of these represents an XTimer. 108 * These are stored in a global linked list. 128 * These are stored in a linked list in 129 * an _XTIMERSET. 109 130 */ 110 131 … … 221 242 */ 222 243 223 PXTIMER FindTimer(PXTIMERSET pSet, 224 HWND hwnd, 225 USHORT usTimerID) 244 PXTIMER FindTimer(PXTIMERSET pSet, // in: timer set (from tmrCreateSet) 245 HWND hwnd, // in: timer target window 246 USHORT usTimerID) // in: timer ID 226 247 { 227 248 if (pSet && pSet->pvllXTimers) … … 252 273 * 253 274 * Internal function. 254 * 255 * Preconditions: 256 * 257 * -- The caller must call LockTimers() first. 258 */ 259 260 VOID RemoveTimer(PXTIMERSET pSet, 261 PXTIMER pTimer) 275 */ 276 277 VOID RemoveTimer(PXTIMERSET pSet, // in: timer set (from tmrCreateSet) 278 PXTIMER pTimer) // in: timer to remove. 262 279 { 263 280 if (pSet && pSet->pvllXTimers) … … 266 283 lstRemoveItem(pllXTimers, 267 284 pTimer); // auto-free! 268 /* if (lstCountItems(&G_llTimers) == 0)269 // no more timers left:270 // stop the main timer271 thrClose(&G_tiTimers); */272 285 } 273 286 } … … 284 297 * This is the first step if you want to use the XTimers. 285 298 * 299 * hwndOwner must specify the "owner window", the target 300 * window for the master PM timer. This window must respond 301 * to a WM_TIMER message with the specified usPMTimerID and 302 * invoke tmrTimerTick then. 303 * 304 * Note that the master timer is not started until an XTimer 305 * is started. 306 * 286 307 * Use tmrDestroySet to free all resources again. 287 308 * … … 289 310 */ 290 311 291 PXTIMERSET tmrCreateSet(HWND hwndOwner, 312 PXTIMERSET tmrCreateSet(HWND hwndOwner, // in: owner window 292 313 USHORT usPMTimerID) 293 314 { 294 315 PXTIMERSET pSet = NULL; 295 296 // _Pmpf((__FUNCTION__ ": entering"));297 316 298 317 pSet = (PXTIMERSET)malloc(sizeof(*pSet)); … … 303 322 pSet->idPMTimer = usPMTimerID; 304 323 pSet->idPMTimerRunning = 0; 324 pSet->ulPMTimeout = 0; 305 325 306 326 pSet->pvllXTimers = (PVOID)lstCreate(TRUE); 307 327 } 308 309 // _Pmpf((__FUNCTION__ ": leaving, returning 0x%lX", pSet));310 328 311 329 return (pSet); … … 323 341 */ 324 342 325 VOID tmrDestroySet(PXTIMERSET pSet) 326 { 327 // _Pmpf((__FUNCTION__ ": entering")); 328 343 VOID tmrDestroySet(PXTIMERSET pSet) // in: timer set (from tmrCreateSet) 344 { 329 345 if (pSet) 330 346 { … … 344 360 } 345 361 362 if (pSet->idPMTimerRunning) 363 WinStopTimer(pSet->hab, 364 pSet->hwndOwner, 365 pSet->idPMTimer); 366 346 367 free(pSet); 347 368 } 348 349 // _Pmpf((__FUNCTION__ ": leaving")); 369 } 370 371 /* 372 *@@ AdjustPMTimer: 373 * goes thru all XTimers in the sets and starts 374 * or stops the PM timer with a decent frequency. 375 * 376 *@@added V0.9.9 (2001-03-07) [umoeller] 377 */ 378 379 VOID AdjustPMTimer(PXTIMERSET pSet) 380 { 381 PLINKLIST pllXTimers = (PLINKLIST)pSet->pvllXTimers; 382 PLISTNODE pNode = lstQueryFirstNode(pllXTimers); 383 if (!pNode) 384 { 385 // no XTimers running: 386 if (pSet->idPMTimerRunning) 387 { 388 // but PM timer running: 389 // stop it 390 WinStopTimer(pSet->hab, 391 pSet->hwndOwner, 392 pSet->idPMTimer); 393 pSet->idPMTimerRunning = 0; 394 } 395 396 pSet->ulPMTimeout = 0; 397 } 398 else 399 { 400 // we have timers: 401 ULONG ulOldPMTimeout = pSet->ulPMTimeout; 402 pSet->ulPMTimeout = 1000; 403 404 while (pNode) 405 { 406 PXTIMER pTimer = (PXTIMER)pNode->pItemData; 407 408 if ( (pTimer->ulTimeout / 2) < pSet->ulPMTimeout ) 409 pSet->ulPMTimeout = pTimer->ulTimeout / 2; 410 411 pNode = pNode->pNext; 412 } 413 414 if ( (pSet->idPMTimerRunning == 0) // timer not running? 415 || (pSet->ulPMTimeout != ulOldPMTimeout) // timeout changed? 416 ) 417 // start or restart PM timer 418 pSet->idPMTimerRunning = WinStartTimer(pSet->hab, 419 pSet->hwndOwner, 420 pSet->idPMTimer, 421 pSet->ulPMTimeout); 422 } 350 423 } 351 424 … … 364 437 */ 365 438 366 VOID tmrTimerTick(PXTIMERSET pSet) 367 { 368 // _Pmpf((__FUNCTION__ ": entering")); 369 439 VOID tmrTimerTick(PXTIMERSET pSet) // in: timer set (from tmrCreateSet) 440 { 370 441 if (pSet && pSet->pvllXTimers) 371 442 { … … 376 447 PLISTNODE pTimerNode = lstQueryFirstNode(pllXTimers); 377 448 378 // stop the PM timer for now; we'll restart it later 379 WinStopTimer(pSet->hab, 380 pSet->hwndOwner, 381 pSet->idPMTimer); 382 pSet->idPMTimerRunning = 0; 383 384 if (pTimerNode) 449 if (!pTimerNode) 450 { 451 // no timers left: 452 if (pSet->idPMTimerRunning) 453 { 454 // but PM timer running: 455 // stop it 456 WinStopTimer(pSet->hab, 457 pSet->hwndOwner, 458 pSet->idPMTimer); 459 pSet->idPMTimerRunning = 0; 460 } 461 462 pSet->ulPMTimeout = 0; 463 } 464 else 385 465 { 386 466 // we have timers: 387 467 BOOL fFoundInvalid = FALSE; 388 468 389 ULONG ulInterval = 100,469 ULONG // ulInterval = 100, 390 470 ulTimeNow = 0; 391 471 … … 432 512 } // end if (pTimer->ulNextFire < ulTimeNow) 433 513 434 // adjust DosSleep interval435 if (pTimer->ulTimeout < ulInterval)436 ulInterval = pTimer->ulTimeout;437 438 514 // next timer 439 515 pTimerNode = pTimerNode->pNext; … … 452 528 } 453 529 lstClear(&llInvalidTimers); 454 } 455 456 if (lstCountItems(pllXTimers)) 457 { 458 // any timers left: 459 // restart timer with the timeout calculated above 460 pSet->idPMTimerRunning = WinStartTimer(pSet->hab, 461 pSet->hwndOwner, 462 pSet->idPMTimer, 463 ulInterval); 464 /* _Pmpf((" %d timers left, restarted PM timer == %d, interval %d", 465 lstCountItems(pllXTimers), 466 pSet->idPMTimerRunning, 467 ulInterval)); 468 _Pmpf((" pSet->hab: 0x%lX, hwndOwner = 0x%lX, usPMTimerID = %d", 469 pSet->hab, 470 pSet->hwndOwner, 471 pSet->idPMTimer)); */ 530 531 AdjustPMTimer(pSet); 472 532 } 473 533 } // end else if (!pTimerNode) 474 534 } 475 476 // _Pmpf((__FUNCTION__ ": leaving"));477 535 } 478 536 … … 496 554 */ 497 555 498 USHORT XWPENTRY tmrStartXTimer(PXTIMERSET pSet, 499 HWND hwnd, 500 USHORT usTimerID, 501 ULONG ulTimeout) 556 USHORT XWPENTRY tmrStartXTimer(PXTIMERSET pSet, // in: timer set (from tmrCreateSet) 557 HWND hwnd, // in: target window for XTimer 558 USHORT usTimerID, // in: timer ID for XTimer's WM_TIMER 559 ULONG ulTimeout) // in: XTimer's timeout 502 560 { 503 561 USHORT usrc = 0; … … 525 583 pTimer->ulNextFire = ulTimeNow + ulTimeout; 526 584 usrc = pTimer->usTimerID; 527 // _Pmpf((" timer existed, reset"));528 585 } 529 586 else … … 544 601 pTimer); 545 602 usrc = pTimer->usTimerID; 546 547 // _Pmpf((" new timer created"));548 603 } 549 604 } … … 552 607 { 553 608 // timer created or reset: 554 // start main PM timer 555 pSet->idPMTimerRunning = WinStartTimer(pSet->hab, 556 pSet->hwndOwner, 557 pSet->idPMTimer, 558 100); 559 // _Pmpf((" started PM timer %d", pSet->idPMTimerRunning)); 609 AdjustPMTimer(pSet); 560 610 } 561 611 } // if ((hwnd) && (ulTimeout)) … … 577 627 */ 578 628 579 BOOL XWPENTRY tmrStopXTimer(PXTIMERSET pSet, 629 BOOL XWPENTRY tmrStopXTimer(PXTIMERSET pSet, // in: timer set (from tmrCreateSet) 580 630 HWND hwnd, 581 631 USHORT usTimerID) … … 593 643 { 594 644 RemoveTimer(pSet, pTimer); 645 // recalculate 646 AdjustPMTimer(pSet); 595 647 brc = TRUE; 596 648 }
Note:
See TracChangeset
for help on using the changeset viewer.