Changeset 176


Ignore:
Timestamp:
Feb 19, 2008, 12:35:23 AM (17 years ago)
Author:
dmik
Message:

kernel: Implemented DOS timer based Qt timers (#35).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel/qeventloop_pm.cpp

    r132 r176  
    6363static HMQ qt_gui_queue = 0;
    6464
     65#ifdef QT_PM_NO_DOSTIMERS
     66static bool     dispatchTimer( uint, QMSG * );
     67#endif
     68static void     activateZeroTimers();
     69
    6570static void     initTimers();
    6671static void     cleanupTimers();
    67 static bool     dispatchTimer( uint, QMSG * );
    68 static bool     activateTimer( uint );
    69 static void     activateZeroTimers();
    7072
    7173static int       numZeroTimers  = 0;            // number of full-speed timers
     
    111113/*!
    112114  \class QPMObjectWindow qwindowdefs.h
    113    
     115
    114116  The QPMObjectWindow class is an auxiliary class for dedicated message
    115117  processing. Its functionality is based on PM object windows. Once an instance
     
    119121  window handle of this object window is necessary to be passed as a HWND
    120122  argument to other calls and/or messages.
    121  
     123
    122124  Instances of this class must be created on the main GUI thread only or on a
    123125  thread that has created a PM message queue and runs the PM message loop
    124126  \b itself. If you create an instance on a thread other than main, make sure
    125127  you destroy it before destroying the thread's message queue.
    126  
     128
    127129  \note WM_CREATE and WM_DESTROY messages are processed internally and not
    128130  delivered do the message() method. Instead, you can use the constructor and
    129131  the destructor of the subclasses, respectively.
    130  
     132
    131133  \note This class is non-portable!
    132134*/
     
    158160/*!
    159161  Destroys this object window.
    160   This method calls destroy() to free the PM object window. 
     162  This method calls destroy() to free the PM object window.
    161163*/
    162164QPMObjectWindow::~QPMObjectWindow()
     
    171173  already created. The handle of the successfully created object window can
    172174  be obtained using the hwnd() method.
    173  
     175
    174176  \note Must be called on the same thread that cosnstructed this instance.
    175177*/
     
    178180    if ( w != NULLHANDLE )
    179181        return FALSE;
    180    
     182
    181183    static const char *ClassName = "QPMObjectWindow";
    182184    static bool classRegistered = FALSE;
    183    
     185
    184186    if ( !classRegistered ) {
    185187        WinRegisterClass( 0, ClassName, windowProc, 0, QWL_USER + sizeof(PVOID) );
     
    193195    if ( w == NULLHANDLE )
    194196        qSystemWarning( "QPMObjectWindow: Failed to create object window" );
    195 #endif   
     197#endif
    196198
    197199    if ( w != NULLHANDLE && qt_gui_queue &&
     
    200202            qt_objWindows.append( &w );
    201203    }
    202    
     204
    203205    return w != NULLHANDLE;
    204206}
     
    209211  The method does nothing but returns \c FALSE  if the window has been
    210212  already destroyed (or never created).
    211  
     213
    212214  \note Must be called on the same thread that cosnstructed this instance.
    213215*/
     
    216218    if ( w == NULLHANDLE )
    217219        return FALSE;
    218    
     220
    219221    if ( qt_gui_queue && qt_WinQueryQueue( 0 ) == qt_gui_queue ) {
    220222        // remove the handle from the 'clean destruction' list
     
    225227    w = 0; // tell windowProc() we're unsafe
    226228    WinDestroyWindow( h );
    227    
     229
    228230    return TRUE;
    229231}
     
    244246        static_cast< QPMObjectWindow * >( WinQueryWindowPtr( hwnd, QWL_USER ) );
    245247    Q_ASSERT( that );
    246    
     248
    247249    // Note: before WinCreateWindow() returns to the constructor or after the
    248250    // destructor has been called, w is 0. We use this to determine that the
     
    251253    if ( !that || !that->w )
    252254        return (MRESULT) FALSE;
    253    
     255
    254256    return that->message( msg, mp1, mp2 );
    255257}
     
    257259/*!
    258260  \fn QPMObjectWindow::send( ULONG msg, MPARAM mp1, MPARAM mp2 ) const
    259  
     261
    260262  Synchronously sends a message \a msg with the given parameters \a mp1 and
    261263  \a mp2 to this window handle and returns a reply from the message() function.
    262  
     264
    263265  \note Must be called on the same thread that cosnstructed this instance.
    264266*/
     
    266268/*!
    267269  \fn QPMObjectWindow::post( ULONG msg, MPARAM mp1, MPARAM mp2 ) const
    268  
     270
    269271  Asynchronously posts a message \a msg with the given parameters \a mp1 and
    270272  \a mp2 to this window handle. Returns \c TRUE on success and \c FALSE
    271273  otherwise.
    272  
     274
    273275  \note Can be called on any thread.
    274276*/
     
    310312        }
    311313        case WM_TIMER: {
     314#ifndef QT_PM_NO_DOSTIMERS
     315            QApplication::sendPostedEvents( NULL, QEvent::Timer );
     316            break;
     317#else // ifndef QT_PM_NO_DOSTIMERS
    312318            USHORT id = SHORT1FROMMP( mp1 );
    313319            QMSG qmsg = { hwnd(), msg, mp1, mp2 };
    314320            dispatchTimer( (uint) id, &qmsg );
    315321            break;
     322#endif // ifndef QT_PM_NO_DOSTIMERS
    316323        }
    317324    }
    318    
     325
    319326    return FALSE;
    320327}
     
    382389  need some extra handling to activate objects at timeout.
    383390
    384   Implementation note: There are two types of timer identifiers. PM
    385   timer ids (internal use) are stored in TimerInfo.  Qt timer ids are
    386   indexes (+1) into the timerVec vector.
     391  There are two implemetations of Qt timers. When QT_PM_NO_DOSTIMERS is defined
     392  (NOT by default), Qt uses PM timers. In this case, there are two types of
     393  timer identifiers. PM timer ids (internal use) are stored in TimerInfo. Qt
     394  timer ids are indexes (+1) into the timerVec vector. Note that this PM timer
     395  based implementation is error-prone due to stupid PM limitations: there are
     396  only several dozens of PM timers per the whole system and this number is
     397  shared across all processes (e.g. if you create too many timers, other
     398  applications that also need them will suck).
     399
     400  When QT_PM_NO_DOSTIMERS is not defined (by default), Qt uses its own timer
     401  implementation based on a signle DosAsyncTimer() and a dedicated timer thread.
     402  This implementation allows virtually unlimited number of Qt timers. In this
     403  case, there is only one type of type identifiers: Qt timer identifiers are
     404  indexes (+1) into the timeDict dictionary.
    387405
    388406  NOTE: These functions are for internal use. QObject::startTimer() and
     
    418436//
    419437
    420 #include "qptrvector.h"
    421 #include "qintdict.h"
    422 
    423 struct TimerInfo {                              // internal timer info
    424     uint     ind;                               // - Qt timer identifier - 1
    425     ULONG    id;                                // - PM timer identifier
    426     bool     zero;                              // - zero timing
    427     QObject *obj;                               // - object to receive events
    428 };
    429 typedef QPtrVector<TimerInfo>  TimerVec;        // vector of TimerInfo structs
    430 typedef QIntDict<TimerInfo> TimerDict;          // fast dict of timers
    431 
    432 static TimerVec  *timerVec  = 0;                // timer vector
    433 static TimerDict *timerDict = 0;                // timer dict
    434 
    435 template <typename T>                           // template to track availability
    436 class QFreeValueList                            // of free (unused) integer
    437 {                                               // values within some interval
     438//
     439// Template to track availability of free (unused) integer values within some
     440// interval. Note that take() and give() maintain spans sorted in ascending
     441// order.
     442//
     443template <typename T>
     444class QFreeValueList
     445{
    438446public:
    439447    QFreeValueList( T min, T max ) : intMin( min ), intMax( max ) {
     
    450458    void give( T val ) {
    451459        Q_ASSERT( val >= intMin && val <= intMax );
     460        // look for the span to join
    452461        typename FreeList::iterator it = freeValues.begin();
    453462        for ( ; it != freeValues.end(); ++ it ) {
    454463            Span &span = (*it);
    455464            if ( val == span.min - 1 ) {
     465                // join the less end of span
    456466                span.min --;
    457467                typename FreeList::iterator it2 = it;
     
    462472                return;
    463473            } else if ( val == span.max + 1 ) {
     474                // join the greater end of span
    464475                span.max ++;
    465476                typename FreeList::iterator it2 = it;
     
    469480                }
    470481                return;
     482            } else if ( val < span.min ) {
     483                // all the following spans are too "far" to join
     484                break;
    471485            }
    472             else if ( val < span.min )
    473                 break;
     486            // span must not include val (contradicts take())
    474487            Q_ASSERT( val > span.max );
    475488        }
     
    493506};
    494507
     508#ifndef QT_PM_NO_DOSTIMERS
     509
     510#include "qintdict.h"
     511
     512struct TimerInfo {              // internal timer info
     513    uint     ind;               // - Qt timer identifier - 1 (= index in vector)
     514    ULONG    interval;          // - timeout interval, milliseconds
     515    ULONG    last;              // - last shot timestamp
     516    QObject *obj;               // - object to receive events
     517};
     518
     519typedef QIntDict<TimerInfo> TimerDict;          // dict of TimerInfo structs
     520static TimerDict *timerDict = NULL;
     521
     522static QMutex timerMutex;                       // mutex protecting timerDict
     523
     524typedef QFreeValueList<int> FreeQtTIDList;      // list of free Qt timer IDs
     525static FreeQtTIDList *freeQtTIDs = NULL;
     526
     527//
     528// Auxiliary timer thread to wait for Dos timer events and post Qt timer events.
     529//
     530static class QTimerThread : public QThread
     531{
     532public:
     533    QTimerThread();
     534    virtual ~QTimerThread();
     535    void run();
     536    void signalQuit();
     537    void ensureShot( int ival );
     538private:
     539    HEV hev;                        // OS/2 timer event semaphore
     540    HTIMER htimer;                  // OS/2 timer
     541    ULONG interval;                 // OS/2 timer interval
     542    bool quit : 1;                  // quit flag
     543} *timerThread = NULL;
     544
     545QTimerThread::QTimerThread()
     546    : hev( NULLHANDLE ), htimer( NULLHANDLE )
     547    , interval( 0 ), quit( false )
     548{
     549    APIRET rc;
     550    rc = DosCreateEventSem( NULL, &hev, DC_SEM_SHARED, 0 /* reset */);
     551    Q_ASSERT( rc == NO_ERROR );
     552}
     553
     554QTimerThread::~QTimerThread()
     555{
     556    if ( hev != NULLHANDLE ) {
     557        DosCloseEventSem( hev );
     558        hev = NULLHANDLE;
     559    }
     560}
     561
     562void QTimerThread::run()
     563{
     564    APIRET rc;
     565    ULONG now = 0;
     566
     567    do {
     568        rc = DosWaitEventSem( hev, SEM_INDEFINITE_WAIT );
     569        Q_ASSERT( rc == NO_ERROR );
     570        if ( quit )
     571            break;
     572
     573        // get current time again and calculate the interval
     574        DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &now, sizeof(now) );
     575
     576        // go through all timers and see which were shot
     577
     578        QMutexLocker lock( &timerMutex );
     579
     580        ULONG minLeft = ULONG_MAX;
     581
     582        QIntDictIterator<TimerInfo> it( *timerDict );
     583        for ( register TimerInfo *t; (t = it.current()); ++it ) {
     584            ULONG spent = now - t->last;
     585            if ( spent >= t->interval ) {
     586                // the timer iterval has expired, post the timer event
     587                QTimerEvent *e = new QTimerEvent( t->ind + 1 );
     588                QApplication::postEvent( t->obj, e );
     589                // set the new last stamp
     590                t->last += t->interval * (spent / t->interval);
     591            }
     592            // calculate minimal time to the next shot
     593            minLeft = QMIN( minLeft, t->interval - (spent % t->interval) );
     594        }
     595
     596        if ( timerDict->count() > 0 ) {
     597            // post a spare WM_TIMER message to make sure timers run even when
     598            // the message loop is not controlled by QEventLoop::processEvents()
     599            // (e.g. when moving or resizing a window using the mouse)
     600            WinPostMsg( qt_aux_win.hwnd(), WM_TIMER, 0, 0 );
     601            // restart the OS/2 timer
     602            interval = minLeft;
     603            ULONG postCnt;
     604            DosResetEventSem( hev, &postCnt );
     605            // check for quit (cancelQuit() could post the semaphore just before
     606            // we reset it above)
     607            if ( quit )
     608                break;
     609            rc = DosAsyncTimer( minLeft, (HSEM) hev, &htimer );
     610            Q_ASSERT( rc == NO_ERROR );
     611        } else {
     612            htimer = NULLHANDLE;
     613            interval = 0;
     614        }
     615
     616    } while (1);
     617}
     618
     619void QTimerThread::signalQuit()
     620{
     621    quit = true;
     622    DosPostEventSem( hev );
     623    wait();
     624}
     625
     626// Note: must be called from under timerMutex!
     627void QTimerThread::ensureShot( int ival )
     628{
     629    Q_ASSERT( timerMutex.locked() );
     630    Q_ASSERT( ival > 0 );
     631    if ( interval == 0 || interval > (ULONG) ival ) {
     632        // start another timer to make sure the new Qt timer is fired off in time
     633        interval = (ULONG) ival;
     634        APIRET rc = DosAsyncTimer( interval, (HSEM) hev, &htimer );
     635        Q_ASSERT( rc == NO_ERROR );
     636    }
     637}
     638
     639#else // ifndef QT_PM_NO_DOSTIMERS
     640
     641#include "qptrvector.h"
     642#include "qintdict.h"
     643
     644struct TimerInfo {                              // internal timer info
     645    uint     ind;                               // - Qt timer identifier - 1
     646    ULONG    id;                                // - PM timer identifier
     647    bool     zero;                              // - zero timing
     648    QObject *obj;                               // - object to receive events
     649};
     650typedef QPtrVector<TimerInfo>  TimerVec;        // vector of TimerInfo structs
     651typedef QIntDict<TimerInfo> TimerDict;          // fast dict of timers
     652
     653static TimerVec  *timerVec  = 0;                // timer vector
     654static TimerDict *timerDict = 0;                // timer dict
     655
    495656typedef QFreeValueList<int> FreeQtTIDList;      // list of free Qt timer IDs
    496657static FreeQtTIDList *freeQtTIDs = 0;
     
    498659static FreePMTIDList *freePMTIDs = 0;
    499660
    500 // Activate a timer, used by both event-loop based and simple timers.
    501 
    502 static bool dispatchTimer( uint timerId, QMSG *msg )
    503 {
    504     MRESULT res = NULL;
    505     if ( !msg || !qApp || !qt_pmEventFilter(msg,res) )
    506         return activateTimer( timerId );
    507     return TRUE;
    508 }
    509 
    510 
    511661//
    512662// Timer activation (called from the event loop when WM_TIMER arrives)
    513663//
    514 
    515 static bool activateTimer( uint id )            // activate timer
    516 {
    517     if ( !timerVec )                            // should never happen
    518         return FALSE;
    519     register TimerInfo *t = timerDict->find( id );
    520     if ( !t )                                   // no such timer id
    521         return FALSE;
    522     QTimerEvent e( t->ind + 1 );
    523     QApplication::sendEvent( t->obj, &e );      // send event
    524     return TRUE;                                // timer event was processed
    525 }
    526 
    527 static void activateZeroTimers()                // activate full-speed timers
    528 {
     664static bool dispatchTimer( uint timerId, QMSG *msg )
     665{
     666    MRESULT res = NULL;
     667    if ( !msg || !qApp || !qt_pmEventFilter(msg,res) )
     668    {
     669        if ( !timerVec )            // should never happen
     670            return FALSE;
     671        register TimerInfo *t = timerDict->find( timerId );
     672        if ( !t )                   // no such timer id
     673            return FALSE;
     674        QTimerEvent e( t->ind + 1 );
     675        QApplication::sendEvent( t->obj, &e );  // send event
     676        return TRUE;                // timer event was processed
     677    }
     678    return TRUE;
     679}
     680
     681#endif // ifndef QT_PM_NO_DOSTIMERS
     682
     683//
     684// activate full-speed timers
     685//
     686static void activateZeroTimers()
     687{
     688#ifndef QT_PM_NO_DOSTIMERS
     689    if ( !timerDict )
     690        return;
     691    QIntDictIterator<TimerInfo> it( *timerDict );
     692    register TimerInfo *t = 0;
     693    int n = numZeroTimers;
     694    while ( n-- ) {
     695        for ( ;; ) {
     696            t = it();
     697            Q_ASSERT( t );
     698            if ( !t )
     699                return;
     700            if ( t->interval == 0 )
     701                break;
     702        }
     703        QTimerEvent e( t->ind + 1 );
     704        QApplication::sendEvent( t->obj, &e );
     705    }
     706#else
    529707    if ( !timerVec )
    530         return;
     708        return;
    531709    uint i=0;
    532710    register TimerInfo *t = 0;
    533711    int n = numZeroTimers;
    534712    while ( n-- ) {
    535         for ( ;; ) {
    536             t = timerVec->at(i++);
    537             if ( t && t->zero )
    538                 break;
    539             else if ( i == timerVec->size() )           // should not happen
    540                 return;
    541         }
    542         QTimerEvent e( t->ind + 1 );
    543         QApplication::sendEvent( t->obj, &e );
    544     }
     713        for ( ;; ) {
     714            t = timerVec->at(i++);
     715            if ( t && t->zero )
     716                break;
     717            else if ( i == timerVec->size() )           // should not happen
     718                return;
     719        }
     720        QTimerEvent e( t->ind + 1 );
     721        QApplication::sendEvent( t->obj, &e );
     722    }
     723#endif
    545724}
    546725
     
    552731static void initTimers()                        // initialize timers
    553732{
     733#ifndef QT_PM_NO_DOSTIMERS
     734    timerDict = new TimerDict( 29 );
     735    Q_CHECK_PTR( timerDict );
     736    timerDict->setAutoDelete( TRUE );
     737    freeQtTIDs = new FreeQtTIDList( 0, 1023 );  // resonable max amount of timers
     738    Q_CHECK_PTR( freeQtTIDs );
     739    timerThread = new QTimerThread();
     740    Q_CHECK_PTR( timerThread );
     741    timerThread->start();
     742#else // ifndef QT_PM_NO_DOSTIMERS
    554743    timerVec = new TimerVec( 128 );
    555744    Q_CHECK_PTR( timerVec );
     
    557746    timerDict = new TimerDict( 29 );
    558747    Q_CHECK_PTR( timerDict );
    559     freeQtTIDs = new FreeQtTIDList( 0, INT_MAX );
     748    freeQtTIDs = new FreeQtTIDList( 0, 1023 );  // resonable max amount of timers
    560749    Q_CHECK_PTR( freeQtTIDs );
    561750    freePMTIDs = new FreePMTIDList( 1, TID_USERMAX - 1 );
    562751    Q_CHECK_PTR( freePMTIDs );
     752#endif // ifndef QT_PM_NO_DOSTIMERS
    563753}
    564754
     
    573763static void cleanupTimers()                     // remove pending timers
    574764{
     765#ifndef QT_PM_NO_DOSTIMERS
     766    if ( !timerDict )               // no timers were used
     767        return;
     768    timerThread->signalQuit();
     769    delete timerThread;
     770    timerThread = NULL;
     771    delete freeQtTIDs;
     772    freeQtTIDs = NULL;
     773    delete timerDict;
     774    timerDict = NULL;
     775#else // ifndef QT_PM_NO_DOSTIMERS
    575776    register TimerInfo *t;
    576777    if ( !timerVec )                            // no timers were used
     
    589790    delete timerVec;
    590791    timerVec  = 0;
     792#endif // ifndef QT_PM_NO_DOSTIMERS
    591793}
    592794
     
    600802{
    601803    Q_ASSERT( obj );
    602     if ( !obj )
     804    if ( !obj || interval < 0 )
    603805        return 0;
    604    
    605     // lazily create the auxiliary window to process WM_TIMER messages
     806
     807    // lazily create the auxiliary window to process WM_TIMER and
     808    // WM_U_SEM_ZEROTIMER messages
    606809    if ( !qt_aux_win.hwnd() )
    607810        if ( !qt_aux_win.create() )
    608811            return 0;
    609    
    610     register TimerInfo *t;
     812
     813#ifndef QT_PM_NO_DOSTIMERS
     814    if ( !timerDict )                           // initialize timer data
     815        initTimers();
     816#else  // ifndef QT_PM_NO_DOSTIMERS
    611817    if ( !timerVec )                            // initialize timer data
    612         initTimers();
     818        initTimers();
     819#endif // ifndef QT_PM_NO_DOSTIMERS
    613820
    614821    if ( freeQtTIDs->isEmpty() ) {
     
    619826        return 0;
    620827    }
    621    
     828
     829#ifdef QT_PM_NO_DOSTIMERS
    622830    if ( freePMTIDs->isEmpty() ) {
    623831#if defined(QT_CHECK_STATE)
     
    627835        return 0;
    628836    }
    629    
    630     int ind = freeQtTIDs->take();               // get free timer
     837#endif
     838
     839    int ind = freeQtTIDs->take();                       // get free timer
     840
     841#ifndef QT_PM_NO_DOSTIMERS
     842    register TimerInfo *t = new TimerInfo;      // create timer entry
     843    Q_CHECK_PTR( t );
     844    t->ind  = ind;
     845    t->obj  = obj;
     846
     847    t->interval = interval;
     848    if ( t->interval == 0 ) {                   // add zero timer
     849        numZeroTimers++;
     850        // indicate there is a new zero timer
     851        WinPostMsg( qt_aux_win.hwnd(), WM_U_SEM_ZEROTIMER, 0, 0 );
     852    } else {
     853        // set the initial last shot timestamp value to now
     854        DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &t->last, sizeof(t->last) );
     855    }
     856
     857    QMutexLocker lock( &timerMutex );
     858    timerDict->insert( ind, t );                // store in timer dict
     859    if ( t->interval != 0 )
     860        timerThread->ensureShot( t->interval );
     861#else // ifndef QT_PM_NO_DOSTIMERS
    631862    if ( (uint) ind >= timerVec->size() ) {
    632863        uint newSize = timerVec->size() * 4;    // increase the size
    633864        if ( newSize <= (uint) ind )
    634865            newSize = (uint) ind + 1;
    635         timerVec->resize( newSize );
    636     }
    637     t = new TimerInfo;                          // create timer entry
     866        timerVec->resize( newSize );
     867    }
     868
     869    register TimerInfo *t = new TimerInfo;      // create timer entry
    638870    Q_CHECK_PTR( t );
    639871    t->ind  = ind;
     
    659891        }
    660892    }
    661     timerVec->insert( ind, t );                 // store in timer vector
     893    timerVec->insert( ind, t );         // store in timer vector
    662894    if ( !t->zero )
    663         timerDict->insert( t->id, t );          // store in dict
    664     return ind + 1;                             // return index in vector
     895        timerDict->insert( t->id, t );  // store in dict
     896#endif // ifndef QT_PM_NO_DOSTIMERS
     897
     898    return ind + 1;                     // return index in vector
    665899}
    666900
    667901bool qKillTimer( int ind )
    668902{
     903#ifndef QT_PM_NO_DOSTIMERS
     904    if ( !timerDict )
     905        return FALSE;
     906    register TimerInfo *t = timerDict->find( ind-1 );
     907    if ( !t )
     908        return FALSE;
     909    if ( t->interval == 0 ) {
     910        numZeroTimers--;
     911    }
     912    freeQtTIDs->give( t->ind );
     913    QMutexLocker lock( &timerMutex );
     914    timerDict->remove( ind-1 );
     915    return TRUE;
     916#else // ifndef QT_PM_NO_DOSTIMERS
    669917    if ( !timerVec || ind <= 0 || (uint)ind > timerVec->size() )
    670         return FALSE;
     918        return FALSE;
    671919    register TimerInfo *t = timerVec->at(ind-1);
    672920    if ( !t )
    673         return FALSE;
     921        return FALSE;
    674922    if ( t->zero ) {
    675         numZeroTimers--;
     923        numZeroTimers--;
    676924    } else {
    677         WinStopTimer( 0, qt_aux_win.hwnd(), t->id );
     925        WinStopTimer( 0, qt_aux_win.hwnd(), t->id );
    678926        freePMTIDs->give( t->id );
    679927        timerDict->remove( t->id );
     
    682930    timerVec->remove( ind-1 );
    683931    return TRUE;
     932#endif // ifndef QT_PM_NO_DOSTIMERS
    684933}
    685934
    686935bool qKillTimer( QObject *obj )
    687936{
     937#ifndef QT_PM_NO_DOSTIMERS
     938    if ( !timerDict )
     939        return FALSE;
     940    QIntDictIterator<TimerInfo> it ( *timerDict );
     941    for ( register TimerInfo *t; (t = it.current()); ) {
     942        if ( t->obj == obj ) {          // object found
     943            if ( t->interval == 0 ) {
     944                numZeroTimers--;
     945            }
     946            freeQtTIDs->give( t->ind );
     947            QMutexLocker lock( &timerMutex );
     948            timerDict->remove( it.currentKey() );
     949        } else {
     950            ++it;
     951        }
     952    }
     953    return TRUE;
     954#else // ifndef QT_PM_NO_DOSTIMERS
    688955    if ( !timerVec )
    689         return FALSE;
     956        return FALSE;
    690957    register TimerInfo *t;
    691958    for ( uint i=0; i<timerVec->size(); i++ ) {
    692         t = timerVec->at( i );
    693         if ( t && t->obj == obj ) {             // object found
    694             if ( t->zero ) {
    695                 numZeroTimers--;
    696             } else {
    697                 WinStopTimer( 0, qt_aux_win.hwnd(), t->id );
     959        t = timerVec->at( i );
     960        if ( t && t->obj == obj ) {             // object found
     961            if ( t->zero ) {
     962                numZeroTimers--;
     963            } else {
     964                WinStopTimer( 0, qt_aux_win.hwnd(), t->id );
    698965                freePMTIDs->give( t->id );
    699966                timerDict->remove( t->id );
    700967            }
    701968            freeQtTIDs->give( t->ind );
    702             timerVec->remove( i );
    703         }
     969            timerVec->remove( i );
     970        }
    704971    }
    705972    return TRUE;
     973#endif // ifndef QT_PM_NO_DOSTIMERS
    706974}
    707975
     
    8951163    qt_gui_queue = d->hmq;
    8961164
    897     qt_aux_win.setEventLoop( this ); 
     1165    qt_aux_win.setEventLoop( this );
    8981166
    8991167#if defined(QT_THREAD_SUPPORT)
     
    9101178void QEventLoop::cleanup()
    9111179{
    912     cleanupTimers();
    913 
    914     // ss_thread should have been stopped already in appClosingDown()
     1180    // timers should have been already uninitialized in appClosingDown()
     1181#ifndef QT_PM_NO_DOSTIMERS
     1182    Q_ASSERT( timerDict == 0 );
     1183#else
     1184    Q_ASSERT( timerVec == 0 );
     1185#endif
     1186
     1187    // ss_thread should have been already stopped in appClosingDown()
    9151188    Q_ASSERT( ss_thread == 0 );
    916    
    917     qt_aux_win.setEventLoop( 0 ); 
    918    
     1189
     1190    qt_aux_win.setEventLoop( 0 );
     1191
    9191192    // destroy all windows created by QPMObjectWindow instances
    9201193    for ( HWND *w = qt_objWindows.first(); w; w = qt_objWindows.next() ) {
     
    9221195        WinDestroyWindow( *w );
    9231196        // tell QPMObjectWindow the window has been destroyed
    924         *w = 0; 
    925     }
    926    
     1197        *w = 0;
     1198    }
     1199
    9271200    WinDestroyMsgQueue( d->hmq );
    9281201    WinTerminate( d->hab );
     
    9371210void QEventLoop::appClosingDown()
    9381211{
    939     // ensure the thread is terminated before QApplication calls
     1212    // ensure the socket thread is terminated before QApplication calls
    9401213    // QThread::cleanup()
    9411214    if ( ss_thread )
    9421215        ss_cleanup();
     1216    // the same applies to the timer thread
     1217    cleanupTimers();
    9431218}
    9441219
     
    9751250    QMutexLocker locker( &ss_mutex );
    9761251    ss_thread->cancelSelectOrIdle();
    977    
     1252
    9781253    QPtrList<QSockNot>  *list = d->sn_vec[type].list;
    9791254    QSockNot *sn;
     
    10391314    if ( !ss_thread )
    10401315        return; // definitely not found
    1041    
     1316
    10421317    QMutexLocker locker( &ss_mutex );
    10431318    ss_thread->cancelSelectOrIdle();
     
    10941369    if ( !ss_thread )
    10951370        return; // definitely not found
    1096    
     1371
    10971372    QMutexLocker locker( &ss_mutex );
    10981373    ss_thread->cancelSelectOrIdle();
     
    11451420    QApplication::sendPostedEvents();
    11461421
     1422#ifndef QT_PM_NO_DOSTIMERS
     1423    // we've just processed all pending events above, including QEvent::Timer
     1424    // events, so remove spare WM_TIMER messages posted to qt_aux_win for the
     1425    // cases when the message loop is run bypassing this method
     1426    if ( qt_aux_win.hwnd() )
     1427        WinPeekMsg( 0, &msg, qt_aux_win.hwnd(), WM_TIMER, WM_TIMER, PM_REMOVE );
     1428#endif // ifndef QT_PM_NO_DOSTIMERS
     1429
    11471430    if ( flags & ExcludeUserInput ) {
    11481431        while ( WinPeekMsg( 0, &msg, 0, 0, 0, PM_NOREMOVE ) ) {
     
    11631446
    11641447    bool canWait = d->exitloop || d->quitnow ? FALSE : (flags & WaitForMore);
    1165    
     1448
    11661449    if ( canWait ) {
    11671450        // can wait if necessary
     
    11841467        }
    11851468    }
    1186    
     1469
    11871470    if ( msg.msg == WM_QUIT ) {
    11881471        // process the quit request
    11891472#if !defined (QT_NO_SESSIONMANAGER)
    11901473        if ( qt_app_canQuit() ) {
    1191 #endif                   
     1474#endif
    11921475            exit( 0 );
    11931476            return TRUE;
     
    11971480            return TRUE;
    11981481        }
    1199 #endif                   
     1482#endif
    12001483    }
    12011484
     
    12111494            flags |= ExcludeSocketNotifiers;
    12121495    }
    1213    
     1496
    12141497    if ( !handled && msg.msg && (!msg.hwnd || !QWidget::find( msg.hwnd )) ) {
    12151498        handled = qt_pmEventFilter( &msg, res );
     
    12241507        activateSocketNotifiers();
    12251508
    1226     // any pending configs?   
     1509    // any pending configs?
    12271510    if ( configRequests )
    12281511        qPMProcessConfigRequests();
     
    12601543    if ( !ss_thread )
    12611544        return 0;
    1262    
     1545
    12631546    // postpone activation if ss_thread is working with the list
    12641547    if ( !ss_mutex.tryLock() ) {
     
    12791562        if ( FD_ISSET(sn->fd, sn->queue) ) {
    12801563            FD_CLR( sn->fd, sn->queue );
    1281             // reenable the socket to let it participate in the next select() 
     1564            // reenable the socket to let it participate in the next select()
    12821565            FD_SET( sn->fd, sn->active );
    12831566            d->sn_highest = QMAX( d->sn_highest, sn->fd );
Note: See TracChangeset for help on using the changeset viewer.