- Timestamp:
- May 7, 2002, 10:49:29 PM (23 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/helpers/timer.c
r142 r163 111 111 #include "helpers\timer.h" 112 112 113 #define DEBUG_XTIMERS 114 113 115 /* 114 116 *@@category: Helpers\PM helpers\Timer replacements … … 224 226 225 227 static VOID RemoveTimer(PXTIMERSET pSet, // in: timer set (from tmrCreateSet) 226 PXTIMER pTimer) // in: timer to remove .228 PXTIMER pTimer) // in: timer to remove 227 229 { 228 230 PLINKLIST pllXTimers; … … 231 233 ) 232 234 { 235 #ifdef DEBUG_XTIMERS 236 _Pmpf((__FUNCTION__ ": removing timer %d", pTimer->usTimerID)); 237 #endif 233 238 lstRemoveItem(pllXTimers, 234 239 pTimer); // auto-free! … … 458 463 *@@changed V0.9.14 (2001-08-03) [umoeller]: fixed "half frequency" regression caused by frequency optimizations 459 464 *@@changed V0.9.16 (2001-12-18) [umoeller]: now using WinDispatchMsg to avoid crashes during win destruction 465 *@@changed V0.9.19 (2002-05-04) [umoeller]: added excpt handling to avoid hanging all timers on the mutex 460 466 */ 461 467 462 468 VOID tmrTimerTick(PXTIMERSET pSet) // in: timer set (from tmrCreateSet) 463 469 { 464 if (LockTimers()) 465 { 466 PLINKLIST pllXTimers; 467 if ( (pSet) 468 && (pllXTimers = (PLINKLIST)pSet->pvllXTimers) 469 ) 470 { 471 // go thru all XTimers and see which one 472 // has elapsed; for all of these, post WM_TIMER 473 // to the target window proc 474 PLISTNODE pTimerNode = lstQueryFirstNode(pllXTimers); 475 476 if (!pTimerNode) 470 BOOL fLocked = FALSE; 471 472 TRY_LOUD(excpt1) 473 { 474 if (fLocked = LockTimers()) 475 { 476 PLINKLIST pllXTimers; 477 if ( (pSet) 478 && (pllXTimers = (PLINKLIST)pSet->pvllXTimers) 479 ) 477 480 { 478 // no timers left: 479 if (pSet->idPMTimerRunning) 481 // go thru all XTimers and see which one 482 // has elapsed; for all of these, post WM_TIMER 483 // to the target window proc 484 PLISTNODE pTimerNode; 485 486 if (!(pTimerNode = lstQueryFirstNode(pllXTimers))) 480 487 { 481 // but PM timer running: 482 // stop it 483 WinStopTimer(pSet->hab, 484 pSet->hwndOwner, 485 pSet->idPMTimer); 486 pSet->idPMTimerRunning = 0; 488 // no timers left: 489 if (pSet->idPMTimerRunning) 490 { 491 // but PM timer running: 492 // stop it 493 WinStopTimer(pSet->hab, 494 pSet->hwndOwner, 495 pSet->idPMTimer); 496 pSet->idPMTimerRunning = 0; 497 } 498 499 pSet->ulPMTimeout = 0; 487 500 } 488 489 pSet->ulPMTimeout = 0; 490 } 491 else 492 { 493 // we have timers: 494 BOOL fFoundInvalid = FALSE; 495 496 // get current time 497 ULONG ulTimeNow = 0; 498 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, 499 &ulTimeNow, sizeof(ulTimeNow)); 500 501 #ifdef DEBUG_XTIMERS 502 _Pmpf((__FUNCTION__ ": ulTimeNow = %d", ulTimeNow)); 503 #endif 504 505 while (pTimerNode) 501 else 506 502 { 507 // get next node first because the 508 // list can get modified while processing 509 // V0.9.12 (2001-05-24) [umoeller] 510 PLISTNODE pNext = pTimerNode->pNext; 511 512 PXTIMER pTimer = (PXTIMER)pTimerNode->pItemData; 503 // we have timers: 504 BOOL fFoundInvalid = FALSE; 505 506 // get current time 507 ULONG ulTimeNow = 0; 508 DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, 509 &ulTimeNow, sizeof(ulTimeNow)); 513 510 514 511 #ifdef DEBUG_XTIMERS 515 _Pmpf((" timer %d: ulNextFire = %d", 516 lstIndexFromItem(pllXTimers, pTimer), 517 pTimer->ulNextFire)); 512 _Pmpf((__FUNCTION__ ": ulTimeNow = %d", ulTimeNow)); 518 513 #endif 519 514 520 if ( (pTimer) 521 // && (pTimer->ulNextFire < ulTimeNow) 522 // V0.9.14 (2001-08-01) [umoeller] 523 // use <= because otherwise we'll get 524 // only half the frequency... 525 // we get here frequently where the 526 // two values are EXACTLY equal due 527 // to the above optimization (DosQuerySysInfo 528 // called once only for the entire loop) 529 && (pTimer->ulNextFire <= ulTimeNow) 530 ) 515 while (pTimerNode) 531 516 { 532 // this timer has elapsed: 533 // fire! 517 // get next node first because the 518 // list can get modified while processing 519 // V0.9.12 (2001-05-24) [umoeller] 520 PLISTNODE pNext = pTimerNode->pNext; 521 522 PXTIMER pTimer = (PXTIMER)pTimerNode->pItemData; 534 523 535 524 #ifdef DEBUG_XTIMERS 536 _Pmpf((" --> fire!")); 525 _Pmpf((" timer %d: ulNextFire = %d", 526 lstIndexFromItem(pllXTimers, pTimer), 527 pTimer->ulNextFire)); 537 528 #endif 538 529 539 if (WinIsWindow(pSet->hab, 540 pTimer->hwndTarget)) 530 if ( (pTimer) 531 // && (pTimer->ulNextFire < ulTimeNow) 532 // V0.9.14 (2001-08-01) [umoeller] 533 // use <= because otherwise we'll get 534 // only half the frequency... 535 // we get here frequently where the 536 // two values are EXACTLY equal due 537 // to the above optimization (DosQuerySysInfo 538 // called once only for the entire loop) 539 && (pTimer->ulNextFire <= ulTimeNow) 540 ) 541 541 { 542 // window still valid: 543 // get the window's window proc 544 QMSG qmsg; 545 /* PFNWP pfnwp = (PFNWP)WinQueryWindowPtr(pTimer->hwndTarget, 546 QWP_PFNWP); */ 547 548 // moved this up V0.9.14 (2001-08-01) [umoeller] 549 pTimer->ulNextFire = ulTimeNow + pTimer->ulTimeout; 550 551 // call the window proc DIRECTLY 552 // V0.9.16 (2001-12-18) [umoeller]: 553 // now using WinDispatchMsg to avoid crashes 554 // while hwndTarget is being destroyed 555 qmsg.hwnd = pTimer->hwndTarget; 556 qmsg.msg = WM_TIMER; 557 qmsg.mp1 = (MPARAM)pTimer->usTimerID; 558 qmsg.mp2 = (MPARAM)0; 559 qmsg.time = 0; 560 qmsg.ptl.x = 0; 561 qmsg.ptl.y = 0; 562 qmsg.reserved = 0; 563 WinDispatchMsg(pSet->hab, 564 &qmsg); 565 566 /* pfnwp(pTimer->hwndTarget, 567 WM_TIMER, 568 (MPARAM)pTimer->usTimerID, 569 0); */ 570 // V0.9.12 (2001-05-24) [umoeller] 571 // if the winproc chooses to start or 572 // stop a timer, pNext still points 573 // to a valid node... 574 // -- if a timer is removed, that's OK 575 // -- if a timer is added, it is added to 576 // the list, so we'll see it in this loop 577 578 // V0.9.14 (2001-08-01) [umoeller] 579 580 // DO NOT REFERENCE pTimer AFTER THIS CODE; 581 // the winproc might have removed the timer, 582 // and since the list is auto-free, pTimer 583 // might have been freed!! 584 } 585 else 586 { 587 // window has been destroyed: 588 lstRemoveNode(pllXTimers, 589 pTimerNode); 590 // pNext is still valid 591 592 fFoundInvalid = TRUE; 593 } 594 595 } // end if (pTimer->ulNextFire < ulTimeNow) 596 597 // next timer 598 pTimerNode = pNext; // V0.9.12 (2001-05-24) [umoeller] 599 } // end while (pTimerNode) 600 601 // destroy invalid timers, if any 602 if (fFoundInvalid) 603 AdjustPMTimer(pSet); 604 605 } // end else if (!pTimerNode) 606 } // end if (pllXTimers) 607 542 // this timer has elapsed: 543 // fire! 544 545 #ifdef DEBUG_XTIMERS 546 _Pmpf((" --> fire!")); 547 #endif 548 549 if (WinIsWindow(pSet->hab, 550 pTimer->hwndTarget)) 551 { 552 // window still valid: 553 // get the window's window proc 554 QMSG qmsg; 555 PFNWP pfnwp = (PFNWP)WinQueryWindowPtr(pTimer->hwndTarget, 556 QWP_PFNWP); 557 558 // moved this up V0.9.14 (2001-08-01) [umoeller] 559 pTimer->ulNextFire = ulTimeNow + pTimer->ulTimeout; 560 561 // call the window proc DIRECTLY 562 // V0.9.16 (2001-12-18) [umoeller]: 563 // now using WinDispatchMsg to avoid crashes 564 // while hwndTarget is being destroyed 565 /* qmsg.hwnd = pTimer->hwndTarget; 566 qmsg.msg = WM_TIMER; 567 qmsg.mp1 = (MPARAM)pTimer->usTimerID; 568 qmsg.mp2 = (MPARAM)0; 569 qmsg.time = 0; 570 qmsg.ptl.x = 0; 571 qmsg.ptl.y = 0; 572 qmsg.reserved = 0; 573 WinDispatchMsg(pSet->hab, 574 &qmsg); */ 575 576 pfnwp(pTimer->hwndTarget, 577 WM_TIMER, 578 (MPARAM)pTimer->usTimerID, 579 0); 580 // V0.9.12 (2001-05-24) [umoeller] 581 // if the winproc chooses to start or 582 // stop a timer, pNext still points 583 // to a valid node... 584 // -- if a timer is removed, that's OK 585 // -- if a timer is added, it is added to 586 // the list, so we'll see it in this loop 587 588 // V0.9.14 (2001-08-01) [umoeller] 589 590 // DO NOT REFERENCE pTimer AFTER THIS CODE; 591 // the winproc might have removed the timer, 592 // and since the list is auto-free, pTimer 593 // might have been freed!! 594 } 595 else 596 { 597 // window has been destroyed: 598 lstRemoveNode(pllXTimers, 599 pTimerNode); 600 // pNext is still valid 601 602 fFoundInvalid = TRUE; 603 } 604 605 } // end if (pTimer->ulNextFire < ulTimeNow) 606 607 // next timer 608 pTimerNode = pNext; // V0.9.12 (2001-05-24) [umoeller] 609 } // end while (pTimerNode) 610 611 // destroy invalid timers, if any 612 if (fFoundInvalid) 613 AdjustPMTimer(pSet); 614 615 } // end else if (!pTimerNode) 616 } // end if (pllXTimers) 617 } // end if (LockTimers()) 618 } 619 CATCH(excpt1) {} END_CATCH(); 620 621 if (fLocked) 608 622 UnlockTimers(); 609 } // end if (LockTimers())610 623 } 611 624 … … 743 756 { 744 757 PXTIMER pTimer; 758 #ifdef DEBUG_XTIMERS 759 _Pmpf((__FUNCTION__ ": finding timer %d", usTimerID)); 760 #endif 745 761 if (pTimer = FindTimer(pSet, 746 762 hwnd,
Note:
See TracChangeset
for help on using the changeset viewer.