Changeset 44 for trunk/src/helpers/timer.c
- Timestamp:
- Mar 8, 2001, 8:28:45 PM (24 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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.