Ignore:
Timestamp:
Mar 3, 2001, 11:58:48 AM (24 years ago)
Author:
umoeller
Message:

Updated timers.

File:
1 edited

Legend:

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

    r21 r41  
    22/*
    33 *@@sourcefile timer.c:
    4  *      XTimers, which can replace the PM timers.
     4 *      XTimers, which can be used to avoid excessive PM
     5 *      timer usage.
    56 *
    67 *      These timers operate similar to PM timers started
     
    910 *      WM_TIMER messages regularly.
    1011 *
    11  *      Instead of WinStartTimer, use tmrStartTimer.
    12  *      Instead of WinStopTimer, use tmrStopTimer.
     12 *      Instead of WinStartTimer, use tmrStartXTimer.
     13 *      Instead of WinStopTimer, use tmrStopXTimer.
    1314 *
    1415 *      The main advantage of the XTimers is that these
     
    7576#define INCL_DOSERRORS
    7677
     78#define INCL_WINWINDOWMGR
    7779#define INCL_WINMESSAGEMGR
     80#define INCL_WINTIMER
    7881#include <os2.h>
    7982
     
    108111typedef struct _XTIMER
    109112{
    110     USHORT     usTimerID;           // timer ID, as passed to tmrStartTimer
    111     HWND       hwndTarget;          // target window, as passed to tmrStartTimer
     113    USHORT     usTimerID;           // timer ID, as passed to tmrStartXTimer
     114    HWND       hwndTarget;          // target window, as passed to tmrStartXTimer
    112115    ULONG      ulTimeout;           // timer's timeout (in ms)
    113116    ULONG      ulNextFire;          // next time scalar (from dtGetULongTime) to fire at
     
    121124
    122125// timers thread
    123 HMTX                G_hmtxTimers = NULLHANDLE;  // timers lock mutex
    124 THREADINFO          G_tiTimers = {0};           // timers thread (only running
     126// HMTX                G_hmtxTimers = NULLHANDLE;  // timers lock mutex
     127// THREADINFO          G_tiTimers = {0};           // timers thread (only running
    125128                                                // if any timers were requested)
    126 BOOL                G_fTimersThreadRunning = FALSE;
    127 LINKLIST            G_llTimers;         // linked list of XTIMER pointers
    128 
    129 /* ******************************************************************
    130  *
    131  *   Timer helpers
    132  *
    133  ********************************************************************/
    134 
    135 /*
    136  *@@ LockTimers:
    137  *      locks the global timer resources.
    138  *      You MUST call UnlockTimers after this.
    139  */
    140 
    141 BOOL LockTimers(VOID)
    142 {
    143     BOOL brc = FALSE;
    144     if (G_hmtxTimers == NULLHANDLE)
    145     {
    146         // this initializes all globals
    147         lstInit(&G_llTimers,
    148                 TRUE);     // auto-free
    149 
    150         brc = (DosCreateMutexSem(NULL,  // unnamed
    151                                  &G_hmtxTimers,
    152                                  0,     // unshared
    153                                  TRUE)  // lock!
    154                         == NO_ERROR);
    155     }
    156     else
    157         brc = (WinRequestMutexSem(G_hmtxTimers, SEM_INDEFINITE_WAIT)
    158                     == NO_ERROR);
    159     return (brc);
    160 }
    161 
    162 /*
    163  *@@ UnlockTimers:
    164  *      the reverse to LockTimers.
    165  */
    166 
    167 VOID UnlockTimers(VOID)
    168 {
    169     DosReleaseMutexSem(G_hmtxTimers);
    170 }
     129// BOOL                G_fTimersThreadRunning = FALSE;
     130// LINKLIST            G_llTimers;         // linked list of XTIMER pointers
    171131
    172132/*
     
    177137 *
    178138 *      This thread is dynamically started when the
    179  *      first timer is started thru tmrStartTimer.
     139 *      first timer is started thru tmrStartXTimer.
    180140 *      It is automatically stopped (to be precise:
    181141 *      it terminates itself) when the last timer
    182  *      is stopped thru tmrStopTimer, which then
     142 *      is stopped thru tmrStopXTimer, which then
    183143 *      sets the thread's fExit flag to TRUE.
    184144 *
     
    186146 */
    187147
    188 void _Optlink fntTimersThread(PTHREADINFO ptiMyself)
     148/* void _Optlink fntTimersThread(PTHREADINFO ptiMyself)
    189149{
    190150    ULONG       ulInterval = 25;
     
    225185            if (fLocked)
    226186            {
    227                 // go thru all XTimers and see which one
    228                 // has elapsed; for all of these, post WM_TIMER
    229                 // to the target window proc
    230                 PLISTNODE pTimerNode = lstQueryFirstNode(&G_llTimers);
    231                 if (!pTimerNode)
    232                     // no more timers left:
    233                     // terminate thread
    234                     ptiMyself->fExit = TRUE;
    235                 else
    236                 {
    237                     // we have timers:
    238                     BOOL      fFoundInvalid = FALSE;
    239 
    240                     // get current time
    241                     DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
    242                                     &ulTimeNow, sizeof(ulTimeNow));
    243 
    244                     while ((pTimerNode) && (!ptiMyself->fExit))
    245                     {
    246                         PXTIMER pTimer = (PXTIMER)pTimerNode->pItemData;
    247 
    248                         if (pTimer->ulNextFire < ulTimeNow)
    249                         {
    250                             // this timer has elapsed:
    251                             // fire!
    252                             if (WinIsWindow(hab,
    253                                             pTimer->hwndTarget))
    254                             {
    255                                 // window still valid:
    256                                 WinPostMsg(pTimer->hwndTarget,
    257                                            WM_TIMER,
    258                                            (MPARAM)pTimer->usTimerID,
    259                                            0);
    260                                 pTimer->ulNextFire = ulTimeNow + pTimer->ulTimeout;
    261                             }
    262                             else
    263                             {
    264                                 // window has been destroyed:
    265                                 #ifdef __DEBUG__
    266                                     DosBeep(100, 100);
    267                                 #endif
    268                                 lstAppendItem(&llInvalidTimers,
    269                                               (PVOID)pTimerNode);
    270                                 fFoundInvalid = TRUE;
    271                             }
    272                         } // end if (pTimer->ulNextFire < ulTimeNow)
    273 
    274                         // adjust DosSleep interval
    275                         if (pTimer->ulTimeout < ulInterval)
    276                             ulInterval = pTimer->ulTimeout;
    277 
    278                         // next timer
    279                         pTimerNode = pTimerNode->pNext;
    280                     } // end while (pTimerNode)
    281 
    282                     // destroy invalid timers, if any
    283                     if ((fFoundInvalid) && (!ptiMyself->fExit))
    284                     {
    285                         PLISTNODE pNodeNode = lstQueryFirstNode(&llInvalidTimers);
    286                         while (pNodeNode)
    287                         {
    288                             PLISTNODE pNode2Remove = (PLISTNODE)pNodeNode->pItemData;
    289                             lstRemoveNode(&G_llTimers,
    290                                           pNode2Remove);
    291                             pNodeNode = pNodeNode->pNext;
    292                         }
    293                         lstClear(&llInvalidTimers);
    294                     }
    295                 } // end else if (!pTimerNode)
    296187            } // end if (fLocked)
    297188        }
     
    313204        DosBeep(1500, 30);
    314205    #endif
    315 }
     206} */
     207
     208/* ******************************************************************
     209 *
     210 *   Private functions
     211 *
     212 ********************************************************************/
    316213
    317214/*
     
    322219 *
    323220 *      Internal function.
    324  *
    325  *      Preconditions:
    326  *
    327  *      -- The caller must call LockTimers() first.
    328  */
    329 
    330 PXTIMER FindTimer(HWND hwnd,
     221 */
     222
     223PXTIMER FindTimer(PXTIMERSET pSet,
     224                  HWND hwnd,
    331225                  USHORT usTimerID)
    332226{
    333     PLISTNODE pNode = lstQueryFirstNode(&G_llTimers);
    334     while (pNode)
    335     {
    336         PXTIMER pTimer = (PXTIMER)pNode->pItemData;
    337         if (    (pTimer->usTimerID == usTimerID)
    338              && (pTimer->hwndTarget == hwnd)
    339            )
     227    if (pSet && pSet->pvllXTimers)
     228    {
     229        PLINKLIST pllXTimers = (PLINKLIST)pSet->pvllXTimers;
     230        PLISTNODE pNode = lstQueryFirstNode(pllXTimers);
     231        while (pNode)
    340232        {
    341             return (pTimer);
     233            PXTIMER pTimer = (PXTIMER)pNode->pItemData;
     234            if (    (pTimer->usTimerID == usTimerID)
     235                 && (pTimer->hwndTarget == hwnd)
     236               )
     237            {
     238                return (pTimer);
     239            }
     240
     241            pNode = pNode->pNext;
    342242        }
    343 
    344         pNode = pNode->pNext;
    345243    }
     244
    346245    return (NULL);
    347246}
     
    359258 */
    360259
    361 VOID RemoveTimer(PXTIMER pTimer)
    362 {
    363     lstRemoveItem(&G_llTimers,
    364                   pTimer);       // auto-free!
    365     /* if (lstCountItems(&G_llTimers) == 0)
    366         // no more timers left:
    367         // stop the main timer
    368         thrClose(&G_tiTimers); */
     260VOID RemoveTimer(PXTIMERSET pSet,
     261                 PXTIMER pTimer)
     262{
     263    if (pSet && pSet->pvllXTimers)
     264    {
     265        PLINKLIST pllXTimers = (PLINKLIST)pSet->pvllXTimers;
     266        lstRemoveItem(pllXTimers,
     267                      pTimer);       // auto-free!
     268        /* if (lstCountItems(&G_llTimers) == 0)
     269            // no more timers left:
     270            // stop the main timer
     271            thrClose(&G_tiTimers); */
     272    }
    369273}
    370274
    371 /*
    372  *@@ tmrStartTimer:
     275/* ******************************************************************
     276 *
     277 *   Exported functions
     278 *
     279 ********************************************************************/
     280
     281/*
     282 *@@ tmrCreateSet:
     283 *      creates a "timer set" for use with the XTimer functions.
     284 *      This is the first step if you want to use the XTimers.
     285 *
     286 *      Use tmrDestroySet to free all resources again.
     287 *
     288 *@@added V0.9.9 (2001-02-28) [umoeller]
     289 */
     290
     291PXTIMERSET tmrCreateSet(HWND hwndOwner,
     292                        USHORT usPMTimerID)
     293{
     294    PXTIMERSET pSet = NULL;
     295
     296    // _Pmpf((__FUNCTION__ ": entering"));
     297
     298    pSet = (PXTIMERSET)malloc(sizeof(*pSet));
     299    if (pSet)
     300    {
     301        pSet->hab = WinQueryAnchorBlock(hwndOwner);
     302        pSet->hwndOwner = hwndOwner;
     303        pSet->idPMTimer = usPMTimerID;
     304        pSet->idPMTimerRunning = 0;
     305
     306        pSet->pvllXTimers = (PVOID)lstCreate(TRUE);
     307    }
     308
     309    // _Pmpf((__FUNCTION__ ": leaving, returning 0x%lX", pSet));
     310
     311    return (pSet);
     312}
     313
     314/*
     315 *@@ tmrDestroySet:
     316 *      destroys a timer set previously created using
     317 *      tmrCreateSet.
     318 *
     319 *      Of course, this will stop all XTimers which
     320 *      might still be running with this set.
     321 *
     322 *@@added V0.9.9 (2001-02-28) [umoeller]
     323 */
     324
     325VOID tmrDestroySet(PXTIMERSET pSet)
     326{
     327    // _Pmpf((__FUNCTION__ ": entering"));
     328
     329    if (pSet)
     330    {
     331        if (pSet->pvllXTimers)
     332        {
     333            PLINKLIST pllXTimers = (PLINKLIST)pSet->pvllXTimers;
     334
     335            PLISTNODE pTimerNode;
     336
     337            while (pTimerNode = lstQueryFirstNode(pllXTimers))
     338            {
     339                PXTIMER pTimer = (PXTIMER)pTimerNode->pItemData;
     340                RemoveTimer(pSet, pTimer);
     341            }
     342
     343            lstFree(pllXTimers);
     344        }
     345
     346        free(pSet);
     347    }
     348
     349    // _Pmpf((__FUNCTION__ ": leaving"));
     350}
     351
     352/*
     353 *@@ tmrTimerTick:
     354 *      implements a PM timer tick.
     355 *
     356 *      When your window procs receives WM_TIMER for the
     357 *      one PM timer which is supposed to trigger all the
     358 *      XTimers, it must call this function. This will
     359 *      evaluate all XTimers on the list and "fire" them
     360 *      by calling the window procs directly with the
     361 *      WM_TIMER message.
     362 *
     363 *@@added V0.9.9 (2001-02-28) [umoeller]
     364 */
     365
     366VOID tmrTimerTick(PXTIMERSET pSet)
     367{
     368    // _Pmpf((__FUNCTION__ ": entering"));
     369
     370    if (pSet && pSet->pvllXTimers)
     371    {
     372        PLINKLIST pllXTimers = (PLINKLIST)pSet->pvllXTimers;
     373        // go thru all XTimers and see which one
     374        // has elapsed; for all of these, post WM_TIMER
     375        // to the target window proc
     376        PLISTNODE pTimerNode = lstQueryFirstNode(pllXTimers);
     377
     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)
     385        {
     386            // we have timers:
     387            BOOL    fFoundInvalid = FALSE;
     388
     389            ULONG   ulInterval = 100,
     390                    ulTimeNow = 0;
     391
     392            // linked list of timers found to be invalid;
     393            // this holds LISTNODE pointers from the global
     394            // list to be removed
     395            LINKLIST    llInvalidTimers;
     396            lstInit(&llInvalidTimers,
     397                    FALSE);     // no auto-free
     398
     399            // get current time
     400            DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
     401                            &ulTimeNow, sizeof(ulTimeNow));
     402
     403            while (pTimerNode)
     404            {
     405                PXTIMER pTimer = (PXTIMER)pTimerNode->pItemData;
     406
     407                if (pTimer->ulNextFire < ulTimeNow)
     408                {
     409                    // this timer has elapsed:
     410                    // fire!
     411                    if (WinIsWindow(pSet->hab,
     412                                    pTimer->hwndTarget))
     413                    {
     414                        // window still valid:
     415                        // get the window's window proc
     416                        PFNWP pfnwp = (PFNWP)WinQueryWindowPtr(pTimer->hwndTarget,
     417                                                               QWP_PFNWP);
     418                        // call the window proc DIRECTLY
     419                        pfnwp(pTimer->hwndTarget,
     420                              WM_TIMER,
     421                              (MPARAM)pTimer->usTimerID,
     422                              0);
     423                        pTimer->ulNextFire = ulTimeNow + pTimer->ulTimeout;
     424                    }
     425                    else
     426                    {
     427                        // window has been destroyed:
     428                        lstAppendItem(&llInvalidTimers,
     429                                      (PVOID)pTimerNode);
     430                        fFoundInvalid = TRUE;
     431                    }
     432                } // end if (pTimer->ulNextFire < ulTimeNow)
     433
     434                // adjust DosSleep interval
     435                if (pTimer->ulTimeout < ulInterval)
     436                    ulInterval = pTimer->ulTimeout;
     437
     438                // next timer
     439                pTimerNode = pTimerNode->pNext;
     440            } // end while (pTimerNode)
     441
     442            // destroy invalid timers, if any
     443            if (fFoundInvalid)
     444            {
     445                PLISTNODE pNodeNode = lstQueryFirstNode(&llInvalidTimers);
     446                while (pNodeNode)
     447                {
     448                    PLISTNODE pNode2Remove = (PLISTNODE)pNodeNode->pItemData;
     449                    lstRemoveNode(pllXTimers,
     450                                  pNode2Remove);
     451                    pNodeNode = pNodeNode->pNext;
     452                }
     453                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)); */
     472            }
     473        } // end else if (!pTimerNode)
     474    }
     475
     476    // _Pmpf((__FUNCTION__ ": leaving"));
     477}
     478
     479/*
     480 *@@ tmrStartXTimer:
    373481 *      starts an XTimer.
    374482 *
     
    380488 *      Returns a new timer or resets an existing
    381489 *      timer (if usTimerID is already used with
    382  *      hwnd). Use tmrStopTimer to stop the timer.
     490 *      hwnd). Use tmrStopXTimer to stop the timer.
    383491 *
    384492 *      The timer is _not_ stopped automatically
     
    388496 */
    389497
    390 USHORT APIENTRY tmrStartTimer(HWND hwnd,
    391                               USHORT usTimerID,
    392                               ULONG ulTimeout)
     498USHORT XWPENTRY tmrStartXTimer(PXTIMERSET pSet,
     499                               HWND hwnd,
     500                               USHORT usTimerID,
     501                               ULONG ulTimeout)
    393502{
    394503    USHORT  usrc = 0;
    395     BOOL    fLocked = FALSE;
    396 
    397     if ((hwnd) && (ulTimeout))
    398     {
    399         ULONG ulNesting = 0;
    400         DosEnterMustComplete(&ulNesting);
    401 
    402         TRY_LOUD(excpt1)
     504
     505    // _Pmpf((__FUNCTION__ ": entering"));
     506
     507    if (pSet && pSet->pvllXTimers)
     508    {
     509        PLINKLIST pllXTimers = (PLINKLIST)pSet->pvllXTimers;
     510
     511        if ((hwnd) && (ulTimeout))
    403512        {
    404             fLocked = LockTimers();
    405             if (fLocked)
    406             {
    407                 PXTIMER pTimer;
    408 
    409                 // if the timers thread is not yet running,
    410                 // start it now (i.e. this is the first timer)
    411                 if (!G_fTimersThreadRunning)
    412                 {
    413                     // main timer not yet running:
    414                     thrCreate(&G_tiTimers,
    415                               fntTimersThread,
    416                               &G_fTimersThreadRunning,
    417                               THRF_WAIT,        // no msgq, but wait
    418                               0);
    419                     // raise priority
    420                     DosSetPriority(PRTYS_THREAD,
    421                                    PRTYC_REGULAR,  // 3
    422                                    PRTYD_MAXIMUM,
    423                                    G_tiTimers.tid);
    424                 }
    425 
    426                 // check if this timer exists already
    427                 pTimer = FindTimer(hwnd,
    428                                    usTimerID);
     513            PXTIMER pTimer;
     514
     515            // check if this timer exists already
     516            pTimer = FindTimer(pSet,
     517                               hwnd,
     518                               usTimerID);
     519            if (pTimer)
     520            {
     521                // exists already: reset only
     522                ULONG ulTimeNow;
     523                DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
     524                                &ulTimeNow, sizeof(ulTimeNow));
     525                pTimer->ulNextFire = ulTimeNow + ulTimeout;
     526                usrc = pTimer->usTimerID;
     527                // _Pmpf(("  timer existed, reset"));
     528            }
     529            else
     530            {
     531                // new timer needed:
     532                pTimer = (PXTIMER)malloc(sizeof(XTIMER));
    429533                if (pTimer)
    430534                {
    431                     // exists already: reset only
    432535                    ULONG ulTimeNow;
    433536                    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
    434537                                    &ulTimeNow, sizeof(ulTimeNow));
     538                    pTimer->usTimerID = usTimerID;
     539                    pTimer->hwndTarget = hwnd;
     540                    pTimer->ulTimeout = ulTimeout;
    435541                    pTimer->ulNextFire = ulTimeNow + ulTimeout;
     542
     543                    lstAppendItem(pllXTimers,
     544                                  pTimer);
    436545                    usrc = pTimer->usTimerID;
    437                 }
    438                 else
    439                 {
    440                     // new timer needed:
    441                     pTimer = (PXTIMER)malloc(sizeof(XTIMER));
    442                     if (pTimer)
    443                     {
    444                         ULONG ulTimeNow;
    445                         DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
    446                                         &ulTimeNow, sizeof(ulTimeNow));
    447                         pTimer->usTimerID = usTimerID;
    448                         pTimer->hwndTarget = hwnd;
    449                         pTimer->ulTimeout = ulTimeout;
    450                         pTimer->ulNextFire = ulTimeNow + ulTimeout;
    451 
    452                         lstAppendItem(&G_llTimers,
    453                                       pTimer);
    454                         usrc = pTimer->usTimerID;
    455                     }
     546
     547                    // _Pmpf(("  new timer created"));
    456548                }
    457549            }
    458         }
    459         CATCH(excpt1) { } END_CATCH();
    460 
    461         // unlock the sems outside the exception handler
    462         if (fLocked)
    463         {
    464             UnlockTimers();
    465             fLocked = FALSE;
    466         }
    467 
    468         DosExitMustComplete(&ulNesting);
    469     } // if ((hwnd) && (ulTimeout))
     550
     551            if (usrc)
     552            {
     553                // 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));
     560            }
     561        } // if ((hwnd) && (ulTimeout))
     562    }
     563
     564    // _Pmpf((__FUNCTION__ ": leaving, returning %d", usrc));
    470565
    471566    return (usrc);
     
    473568
    474569/*
    475  *@@ tmrStopTimer:
     570 *@@ tmrStopXTimer:
    476571 *      similar to WinStopTimer, this stops the
    477572 *      specified timer (which must have been
    478573 *      started with the same hwnd and usTimerID
    479  *      using tmrStartTimer).
     574 *      using tmrStartXTimer).
    480575 *
    481576 *      Returns TRUE if the timer was stopped.
    482577 */
    483578
    484 BOOL APIENTRY tmrStopTimer(HWND hwnd,
    485                            USHORT usTimerID)
     579BOOL XWPENTRY tmrStopXTimer(PXTIMERSET pSet,
     580                            HWND hwnd,
     581                            USHORT usTimerID)
    486582{
    487583    BOOL brc = FALSE;
    488     BOOL fLocked = FALSE;
    489 
    490     ULONG ulNesting = 0;
    491     DosEnterMustComplete(&ulNesting);
    492 
    493     TRY_LOUD(excpt1)
    494     {
    495         fLocked = LockTimers();
    496         if (fLocked)
     584    if (pSet && pSet->pvllXTimers)
     585    {
     586        PLINKLIST pllXTimers = (PLINKLIST)pSet->pvllXTimers;
     587        BOOL fLocked = FALSE;
     588
     589        PXTIMER pTimer = FindTimer(pSet,
     590                                   hwnd,
     591                                   usTimerID);
     592        if (pTimer)
    497593        {
    498             PXTIMER pTimer = FindTimer(hwnd,
    499                                        usTimerID);
    500             if (pTimer)
    501             {
    502                 RemoveTimer(pTimer);
    503                 brc = TRUE;
    504             }
     594            RemoveTimer(pSet, pTimer);
     595            brc = TRUE;
    505596        }
    506597    }
    507     CATCH(excpt1) { } END_CATCH();
    508 
    509     // unlock the sems outside the exception handler
    510     if (fLocked)
    511     {
    512         UnlockTimers();
    513         fLocked = FALSE;
    514     }
    515 
    516     DosExitMustComplete(&ulNesting);
    517598
    518599    return (brc);
    519600}
    520601
    521 /*
    522  *@@ tmrStopAllTimers:
    523  *      stops all timers which are running for the
    524  *      specified window. This is a useful helper
    525  *      that you should call during WM_DESTROY of
    526  *      a window that has started timers.
    527  */
    528 
    529 VOID tmrStopAllTimers(HWND hwnd)
    530 {
    531     BOOL fLocked = FALSE;
    532 
    533     ULONG ulNesting = 0;
    534     DosEnterMustComplete(&ulNesting);
    535 
    536     TRY_LOUD(excpt1)
    537     {
    538         fLocked = LockTimers();
    539         if (fLocked)
    540         {
    541             PLISTNODE pTimerNode = lstQueryFirstNode(&G_llTimers);
    542             while (pTimerNode)
    543             {
    544                 PXTIMER pTimer = (PXTIMER)pTimerNode->pItemData;
    545                 if (pTimer->hwndTarget == hwnd)
    546                 {
    547                     RemoveTimer(pTimer);
    548                     // start over
    549                     pTimerNode = lstQueryFirstNode(&G_llTimers);
    550                 }
    551                 else
    552                     pTimerNode = pTimerNode->pNext;
    553             }
    554         }
    555     }
    556     CATCH(excpt1) { } END_CATCH();
    557 
    558     // unlock the sems outside the exception handler
    559     if (fLocked)
    560     {
    561         UnlockTimers();
    562         fLocked = FALSE;
    563     }
    564 
    565     DosExitMustComplete(&ulNesting);
    566 }
    567 
    568 
     602
Note: See TracChangeset for help on using the changeset viewer.