Ignore:
Timestamp:
Mar 8, 2001, 8:28:45 PM (24 years ago)
Author:
umoeller
Message:

Misc. changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/helpers/timer.c

    r41 r44  
    55 *      timer usage.
    66 *
    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.
    1429 *
    1530 *      The main advantage of the XTimers is that these
     
    2742 *          running.
    2843 *
    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.
    3454 *
    3555 *      --  Queue timers (with HWND == NULLHANDLE) are not
    3656 *          supported.
    3757 *
    38  *      --  When a window is deleted, its timers are not
    39  *          automatically cleaned up. The timer thread does
     58 *      --  When a window is destroyed, its timers are not
     59 *          automatically cleaned up. tmrTimerTick does
    4060 *          detect invalid windows and removes them from the
    4161 *          timers list before posting, but to be on the safe
     
    106126 *@@ XTIMER:
    107127 *      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.
    109130 */
    110131
     
    221242 */
    222243
    223 PXTIMER FindTimer(PXTIMERSET pSet,
    224                   HWND hwnd,
    225                   USHORT usTimerID)
     244PXTIMER FindTimer(PXTIMERSET pSet,          // in: timer set (from tmrCreateSet)
     245                  HWND hwnd,                // in: timer target window
     246                  USHORT usTimerID)         // in: timer ID
    226247{
    227248    if (pSet && pSet->pvllXTimers)
     
    252273 *
    253274 *      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
     277VOID RemoveTimer(PXTIMERSET pSet,       // in: timer set (from tmrCreateSet)
     278                 PXTIMER pTimer)        // in: timer to remove.
    262279{
    263280    if (pSet && pSet->pvllXTimers)
     
    266283        lstRemoveItem(pllXTimers,
    267284                      pTimer);       // auto-free!
    268         /* if (lstCountItems(&G_llTimers) == 0)
    269             // no more timers left:
    270             // stop the main timer
    271             thrClose(&G_tiTimers); */
    272285    }
    273286}
     
    284297 *      This is the first step if you want to use the XTimers.
    285298 *
     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 *
    286307 *      Use tmrDestroySet to free all resources again.
    287308 *
     
    289310 */
    290311
    291 PXTIMERSET tmrCreateSet(HWND hwndOwner,
     312PXTIMERSET tmrCreateSet(HWND hwndOwner,         // in: owner window
    292313                        USHORT usPMTimerID)
    293314{
    294315    PXTIMERSET pSet = NULL;
    295 
    296     // _Pmpf((__FUNCTION__ ": entering"));
    297316
    298317    pSet = (PXTIMERSET)malloc(sizeof(*pSet));
     
    303322        pSet->idPMTimer = usPMTimerID;
    304323        pSet->idPMTimerRunning = 0;
     324        pSet->ulPMTimeout = 0;
    305325
    306326        pSet->pvllXTimers = (PVOID)lstCreate(TRUE);
    307327    }
    308 
    309     // _Pmpf((__FUNCTION__ ": leaving, returning 0x%lX", pSet));
    310328
    311329    return (pSet);
     
    323341 */
    324342
    325 VOID tmrDestroySet(PXTIMERSET pSet)
    326 {
    327     // _Pmpf((__FUNCTION__ ": entering"));
    328 
     343VOID tmrDestroySet(PXTIMERSET pSet)     // in: timer set (from tmrCreateSet)
     344{
    329345    if (pSet)
    330346    {
     
    344360        }
    345361
     362        if (pSet->idPMTimerRunning)
     363            WinStopTimer(pSet->hab,
     364                         pSet->hwndOwner,
     365                         pSet->idPMTimer);
     366
    346367        free(pSet);
    347368    }
    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
     379VOID 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    }
    350423}
    351424
     
    364437 */
    365438
    366 VOID tmrTimerTick(PXTIMERSET pSet)
    367 {
    368     // _Pmpf((__FUNCTION__ ": entering"));
    369 
     439VOID tmrTimerTick(PXTIMERSET pSet)      // in: timer set (from tmrCreateSet)
     440{
    370441    if (pSet && pSet->pvllXTimers)
    371442    {
     
    376447        PLISTNODE pTimerNode = lstQueryFirstNode(pllXTimers);
    377448
    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
    385465        {
    386466            // we have timers:
    387467            BOOL    fFoundInvalid = FALSE;
    388468
    389             ULONG   ulInterval = 100,
     469            ULONG   // ulInterval = 100,
    390470                    ulTimeNow = 0;
    391471
     
    432512                } // end if (pTimer->ulNextFire < ulTimeNow)
    433513
    434                 // adjust DosSleep interval
    435                 if (pTimer->ulTimeout < ulInterval)
    436                     ulInterval = pTimer->ulTimeout;
    437 
    438514                // next timer
    439515                pTimerNode = pTimerNode->pNext;
     
    452528                }
    453529                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);
    472532            }
    473533        } // end else if (!pTimerNode)
    474534    }
    475 
    476     // _Pmpf((__FUNCTION__ ": leaving"));
    477535}
    478536
     
    496554 */
    497555
    498 USHORT XWPENTRY tmrStartXTimer(PXTIMERSET pSet,
    499                                HWND hwnd,
    500                                USHORT usTimerID,
    501                                ULONG ulTimeout)
     556USHORT 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
    502560{
    503561    USHORT  usrc = 0;
     
    525583                pTimer->ulNextFire = ulTimeNow + ulTimeout;
    526584                usrc = pTimer->usTimerID;
    527                 // _Pmpf(("  timer existed, reset"));
    528585            }
    529586            else
     
    544601                                  pTimer);
    545602                    usrc = pTimer->usTimerID;
    546 
    547                     // _Pmpf(("  new timer created"));
    548603                }
    549604            }
     
    552607            {
    553608                // 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);
    560610            }
    561611        } // if ((hwnd) && (ulTimeout))
     
    577627 */
    578628
    579 BOOL XWPENTRY tmrStopXTimer(PXTIMERSET pSet,
     629BOOL XWPENTRY tmrStopXTimer(PXTIMERSET pSet,    // in: timer set (from tmrCreateSet)
    580630                            HWND hwnd,
    581631                            USHORT usTimerID)
     
    593643        {
    594644            RemoveTimer(pSet, pTimer);
     645            // recalculate
     646            AdjustPMTimer(pSet);
    595647            brc = TRUE;
    596648        }
Note: See TracChangeset for help on using the changeset viewer.