Changeset 141 for trunk/src/corelib


Ignore:
Timestamp:
Aug 29, 2009, 5:44:05 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

core: A bunch of fixes to QEventDispatcherPM which actually made Qt timers work. This enabled the I-beam cursor and other timer-dependent operations such as the async directory refresh in the file dialog.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/corelib/kernel/qeventdispatcher_pm.cpp

    r98 r141  
    219219
    220220// socket select notification (higher priority)
    221 #define WM_U_SEM_SELECT     WM_SEM1
     221#define WM_U_SEM_SELECT     WM_
    222222// timer notification (lower priority)
    223 #define WM_U_SEM_TIMER      WM_SEM3 // scheduled right before WM_TIMER
     223#define WM_U_SEM_TIMER      WM_TIMER
    224224
    225225// Internal operator functions for timevals
     
    313313    int refcnt;
    314314    QWaitCondition cond;
     315
    315316
    316317    // socket stuff
     
    465466    instance->timers.insert(t->id, t);
    466467    // QMap is sorted by key (timeval), which is exactly what we need
    467     instance->timersByTimeout.insert(t->timeout, t);
     468    instance->timersByTimeout.insert(t->timeout, t);
    468469
    469470    instance->cancelSelectOrIdle();
     
    573574    if (instance == 0) {
    574575        instance = new QSelectThread();
    575         instance->start();
    576     }
    577 
    578     ++instance->refcnt;
     576    } else {
     577        while (instance->finish) {
     578            // the previous instance is still getting finished; let it go
     579            locker.unlock();
     580            QThread::yieldCurrentThread();
     581            locker.relock();
     582        }
     583    }
     584
     585    // don't count on ourselves
     586    if (instance != QThread::currentThread())
     587        ++instance->refcnt;
    579588}
    580589
     
    592601{
    593602    QMutexLocker locker(&mutex);
    594     Q_ASSERT(instance);
     603
     604    // don't count on ourselves
     605    if (instance == QThread::currentThread())
     606        return;
    595607
    596608    // remove socket notifiers owned by this thread
     
    629641        instance->finish = true;
    630642        instance->cancelSelectOrIdle();
     643
     644
    631645        instance->wait();
     646
    632647        delete instance;
    633648        instance = 0;
     
    637652}
    638653
    639 QSelectThread::QSelectThread() : finish(false), refcnt(0)
     654QSelectThread::QSelectThread() : finish(false), refcnt(0)
    640655{
    641656    // initialize socket stuff
     
    681696
    682697    do {
    683         while (!finish && sockets.isEmpty()) {
    684             cond.wait(&mutex);
     698        while (!finish && sockets.isEmpty() && timers.isEmpty()) {
     699            if (!cancelWait)
     700                cond.wait(&mutex);
     701            cancelWait = false;
    685702        }
    686703
     
    735752            timeout = &wait_tm;
    736753
    737         mutex.unlock();
    738 
    739         // do select
    740         int nsel = ::select(maxSockfd + 1, &readS, &writeS, &exS, timeout);
    741         if (nsel > 0) {
    742             for (Hwnds::const_iterator it = hwnds.constBegin();
    743                   it != hwnds.constEnd(); ++it) {
    744                 int sockfd = toSocket(it.key());
    745                 bool isSet = false;
    746                 switch (toSockType(it.key())) {
    747                     case QSocketNotifier::Read:
    748                         isSet = FD_ISSET(sockfd, &readS); break;
    749                     case QSocketNotifier::Write:
    750                         isSet = FD_ISSET(sockfd, &writeS); break;
    751                     case QSocketNotifier::Exception:
    752                         isSet = FD_ISSET(sockfd, &exS); break;
     754        // do select or simple wait
     755        int nsel = 0;
     756        if (maxSockfd >= 0) {
     757            mutex.unlock();
     758            nsel = ::select(maxSockfd + 1, &readS, &writeS, &exS, timeout);
     759            if (nsel > 0) {
     760                for (Hwnds::const_iterator it = hwnds.constBegin();
     761                      it != hwnds.constEnd(); ++it) {
     762                    int sockfd = toSocket(it.key());
     763                    bool isSet = false;
     764                    switch (toSockType(it.key())) {
     765                        case QSocketNotifier::Read:
     766                            isSet = FD_ISSET(sockfd, &readS); break;
     767                        case QSocketNotifier::Write:
     768                            isSet = FD_ISSET(sockfd, &writeS); break;
     769                        case QSocketNotifier::Exception:
     770                            isSet = FD_ISSET(sockfd, &exS); break;
     771                    }
     772                    if (isSet)
     773                        WinPostMsg(it.value(), WM_U_SEM_SELECT, MPFROMLONG(it.key()), 0);
    753774                }
    754                 if (isSet)
    755                     WinPostMsg(it.value(), WM_U_SEM_SELECT, MPFROMLONG(it.key()), 0);
    756775            }
    757         }
    758 
    759         mutex.lock();
     776            mutex.lock();
     777        } else {
     778            ulong msecs = timeout ?
     779                timeout->tv_sec * 1000 + timeout->tv_usec / 1000 : ULONG_MAX;
     780            if (!cancelWait) {
     781                if (cond.wait(&mutex, msecs))
     782                    nsel = -2; // avoid activation on when cancelled
     783            } else {
     784                nsel = -2; // same as above
     785            }
     786            cancelWait = false;
     787        }
    760788
    761789        if (nsel == 0 || (nsel == -1 && errno == EINTR)) {
     
    775803        ::so_cancel(maxSockfd);
    776804    } else {
    777         // terminate the idle state
    778         cond.wakeOne();
     805        // terminate the idle or simple wait state
     806        if (!cancelWait) {
     807            cancelWait = true;
     808            cond.wakeOne();
     809        }
    779810    }
    780811}
     
    856887{
    857888    // repair all timers
     889
    858890    for (TimerInfoMap::iterator it = instance->timers.begin();
    859891          it != instance->timers.end(); ++it) {
    860892        register TimerInfo *t = it.value();
    861893        t->timeout = t->timeout - diff;
     894
    862895    }
    863896}
     
    920953
    921954        // reinsert timer (in proper sort order)
    922         timersByTimeout.insert(t->timeout, t);
     955        timersByTimeout.insert(t->timeout, t);
    923956
    924957        // post the timer message
Note: See TracChangeset for help on using the changeset viewer.