Ignore:
Timestamp:
Jul 26, 2009, 1:19:03 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

corelib: Implemented timers (#24).

Location:
trunk/src/corelib/kernel
Files:
2 edited

Legend:

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

    r83 r84  
    4949#include "qmutex.h"
    5050#include "qwaitcondition.h"
     51
     52
     53
     54
    5155
    5256#include "qabstracteventdispatcher_p.h"
     
    5963
    6064#include <sys/socket.h>
     65
     66
    6167
    6268QT_BEGIN_NAMESPACE
    6369
    6470extern uint qGlobalPostedEventsCount();
    65 
    66 class QEventDispatcherPMPrivate;
    67 
    68 // @todo later: timers
    69 #if 0
    70 
    71 struct WinTimerInfo {                           // internal timer info
    72     QObject *dispatcher;
    73     int timerId;
    74     int interval;
    75     QObject *obj;                               // - object to receive events
    76     bool inTimerEvent;
    77     int fastTimerId;
    78 };
    79 
    80 class QZeroTimerEvent : public QTimerEvent
    81 {
    82 public:
    83     inline QZeroTimerEvent(int timerId)
    84         : QTimerEvent(timerId)
    85     { t = QEvent::ZeroTimerEvent; }
    86 };
    87 
    88 typedef QList<WinTimerInfo*>  WinTimerVec;      // vector of TimerInfo structs
    89 typedef QHash<int, WinTimerInfo*> WinTimerDict; // fast dict of timers
    90 
    91 #if !defined(DWORD_PTR) && !defined(Q_WS_WIN64)
    92 #define DWORD_PTR DWORD
    93 #endif
    94 
    95 typedef MMRESULT(WINAPI *ptimeSetEvent)(UINT, UINT, LPTIMECALLBACK, DWORD_PTR, UINT);
    96 typedef MMRESULT(WINAPI *ptimeKillEvent)(UINT);
    97 
    98 static ptimeSetEvent qtimeSetEvent = 0;
    99 static ptimeKillEvent qtimeKillEvent = 0;
    100 
    101 LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
    102 
    103 static void resolveTimerAPI()
    104 {
    105     static bool triedResolve = false;
    106     if (!triedResolve) {
    107 #ifndef QT_NO_THREAD
    108         QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
    109         if (triedResolve)
    110             return;
    111 #endif
    112         triedResolve = true;
    113 #if !defined(Q_OS_WINCE)
    114         qtimeSetEvent = (ptimeSetEvent)QLibrary::resolve(QLatin1String("winmm"), "timeSetEvent");
    115         qtimeKillEvent = (ptimeKillEvent)QLibrary::resolve(QLatin1String("winmm"), "timeKillEvent");
    116 #else
    117         qtimeSetEvent = (ptimeSetEvent)QLibrary::resolve(QLatin1String("Mmtimer"), "timeSetEvent");
    118         qtimeKillEvent = (ptimeKillEvent)QLibrary::resolve(QLatin1String("Mmtimer"), "timeKillEvent");
    119 #endif
    120     }
    121 }
    122 
    123 #endif
    12471
    12572/*****************************************************************************
     
    272219
    273220
    274 // socket select notification (highest priority)
     221// socket select notification (highe priority)
    275222#define WM_U_SEM_SELECT     WM_SEM1
    276 // zero timer notification (lowest priority)
    277 #define WM_U_SEM_ZEROTIMER  WM_SEM4
     223// timer notification (lower priority)
     224#define WM_U_SEM_TIMER      WM_SEM3 // scheduled right before WM_TIMER
     225
     226// Internal operator functions for timevals
     227
     228inline bool operator<(const timeval &t1, const timeval &t2)
     229{
     230    return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec);
     231}
     232
     233inline bool operator==(const timeval &t1, const timeval &t2)
     234{
     235    return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec;
     236}
     237
     238inline timeval &operator+=(timeval &t1, const timeval &t2)
     239{
     240    t1.tv_sec += t2.tv_sec;
     241    if ((t1.tv_usec += t2.tv_usec) >= 1000000l) {
     242        ++t1.tv_sec;
     243        t1.tv_usec -= 1000000l;
     244    }
     245    return t1;
     246}
     247inline timeval operator+(const timeval &t1, const timeval &t2)
     248{
     249    timeval tmp;
     250    tmp.tv_sec = t1.tv_sec + t2.tv_sec;
     251    if ((tmp.tv_usec = t1.tv_usec + t2.tv_usec) >= 1000000l) {
     252        ++tmp.tv_sec;
     253        tmp.tv_usec -= 1000000l;
     254    }
     255    return tmp;
     256}
     257inline timeval operator-(const timeval &t1, const timeval &t2)
     258{
     259    timeval tmp;
     260    tmp.tv_sec = t1.tv_sec - t2.tv_sec;
     261    if ((tmp.tv_usec = t1.tv_usec - t2.tv_usec) < 0l) {
     262        --tmp.tv_sec;
     263        tmp.tv_usec += 1000000l;
     264    }
     265    return tmp;
     266}
    278267
    279268/*****************************************************************************
    280  socket select() thread
     269 socket select() thread
    281270 *****************************************************************************/
    282271
    283272#if !defined(QT_NO_THREAD)
    284273
    285 class QSockSelectThread : public QThread
     274class QSelectThread : public QThread
    286275{
    287276public:
     277
    288278    typedef QSocketNotifier::Type Type;
    289279
     
    292282    static QSocketNotifier *getSocketNotifier(int key);
    293283
     284
     285
     286
     287
     288
     289
     290
    294291    static void attachThread();
    295292    static void detachThread();
    296293
    297294private:
    298     QSockSelectThread() : finish(false), refcnt(0), maxSockfd(-1) {};
     295    QSelectThread();
     296    ~QSelectThread();
    299297
    300298    void run();
    301299    void cancelSelectOrIdle();
     300
     301
     302
     303
     304
     305
     306
     307
     308
     309
     310
     311
    302312
    303313    bool finish;
     
    305315    QWaitCondition cond;
    306316
     317
     318
    307319    typedef QHash<int, QSocketNotifier*> Sockets;
    308320    Sockets sockets;
     
    310322
    311323    enum Op { Add, Remove };
    312     struct PendingOp {
     324    struct PendingOp {
    313325        Op op;
    314326        int sockfd;
     
    316328        HWND hwnd;
    317329    };
    318     typedef QList<PendingOp> Pending;
    319     Pending pending;
    320 
    321     static int toKey(int sockfd, Type type) {
     330
     331    typedef QList<PendingSockOp> PendingSockets;
     332    PendingSockets pendingSockets;
     333
     334    // timer stuff
     335
     336    struct TimerInfo {
     337        int id;           // - timer identifier
     338        timeval interval; // - timer interval
     339        timeval timeout;  // - when to sent event
     340        QObject *obj;     // - object to receive event
     341        HWND hwnd;        // - where to post the timer message
     342    };
     343
     344    typedef QHash<int, TimerInfo*> TimerInfoMap;
     345    TimerInfoMap timers;
     346
     347    typedef QMap<timeval, TimerInfo*> TimevalMap;
     348    TimevalMap timersByTimeout;
     349
     350    timeval currentTime;
     351    timeval previousTime;
     352    clock_t previousTicks;
     353    int ticksPerSecond;
     354    int msPerTick;
     355
     356    static int toSockKey(int sockfd, Type type) {
    322357        // as a hash key, we use first two bits of int for the type and the rest
    323358        // for the sockfd which should be enough in the real world
     
    325360        return (sockfd << 2) + type;
    326361    }
    327     // opposite to toKey()
     362    // opposite to toKey()
    328363    static int toSocket(int key) { return key >> 2; }
    329     static Type toType(int key) { return Type(key & 0x3); }
    330 
    331     static QSockSelectThread *instance;
     364    static Type toType(int key) { return Type(key & 0x3); }
     365
     366    static QSelectThread *instance;
    332367    static QMutex mutex;
    333368};
    334369
    335370// static
    336 QSockSelectThread *QSockSelectThread::instance = 0;
    337 QMutex QSockSelectThread::mutex;
     371QSSelectThread::instance = 0;
     372QMutex QSelectThread::mutex;
    338373
    339374// static
    340 void QSockSelectThread::addSelect(QSocketNotifier *notifier, HWND hwnd)
     375void QSelectThread::addSelect(QSocketNotifier *notifier, HWND hwnd)
    341376{
    342377    Q_ASSERT(hwnd != NULLHANDLE);
     
    346381    int sockfd = notifier->socket();
    347382    Type type = notifier->type();
    348     int key = toKey(sockfd, type);
     383    int key = toKey(sockfd, type);
    349384
    350385    QMutexLocker locker(&mutex);
    351386    Q_ASSERT(instance);
    352387
     388
    353389    instance->start();
    354390
     
    360396    }
    361397    instance->sockets.insert(key, notifier);
    362     PendingOp op = {Add, sockfd, type, hwnd};
    363     instance->pending.append(op);
     398    PendingOp op = {Add, sockfd, type, hwnd};
     399    instance->pending.append(op);
    364400    instance->cancelSelectOrIdle();
    365401}
    366402
    367403// static
    368 void QSockSelectThread::removeSelect(QSocketNotifier *notifier)
     404void QSelectThread::removeSelect(QSocketNotifier *notifier)
    369405{
    370406    QMutexLocker locker(&mutex);
     
    373409    int sockfd = notifier->socket();
    374410    Type type = notifier->type();
    375     int key = toKey(sockfd, notifier->type());
     411    int key = toKey(sockfd, notifier->type());
    376412
    377413    if (instance->sockets.contains(key)) {
    378414        instance->sockets.remove(key);
    379         PendingOp op = {Remove, sockfd, type};
    380         instance->pending.append(op);
     415        PendingOp op = {Remove, sockfd, type};
     416        instance->pending.append(op);
    381417        instance->cancelSelectOrIdle();
    382418    }
     
    389425
    390426    May return 0 if the socket notifier object is disabled/deleted after
    391     WM_U_SEM_SELECT is issued for it but before this message gets processed by
     427    WM_U_SEM_SELECT s issued for it but before this message gets processed by
    392428    the owning thread.
    393429*/
    394430// static
    395 QSocketNotifier *QSockSelectThread::getSocketNotifier(int key)
     431QSocketNotifier *QSelectThread::getSocketNotifier(int key)
    396432{
    397433    QMutexLocker locker(&mutex);
     
    405441}
    406442
     443
     444
     445
     446
     447
     448
     449
     450
     451
     452
     453
     454
     455
     456
     457
     458
     459
     460
     461
     462
     463
     464
     465
     466
     467
     468
     469
     470
     471
     472
     473
     474
     475
     476
     477
     478
     479
     480
     481
     482
     483
     484
     485
     486
     487
     488
     489
     490
     491
     492
     493
     494
     495
     496
     497
     498
     499
     500
     501
     502
     503
     504
     505
     506
     507
     508
     509
     510
     511
     512
     513
     514
     515
     516
     517
     518
     519
     520
     521
     522
     523
     524
     525
     526
     527
     528
     529
     530
     531
     532
     533
     534
     535
     536
     537
     538
    407539/*!
    408     Incrreases the usage count of the QSockSelectThread instance by one. If no
    409     QSockSelectThread instance exists yet, creates it. Note that the thread is
     540    Returns the timer object corresponding to the given timer ID from the
     541    WM_U_SEM_TIMER message. The return value is only correct for the thread
     542    that owns the timer (creates/registers/unregisters it).
     543
     544    May return 0 if the timer is stopped/deleted after WM_U_SEM_TIMER was issued
     545    for it but before this message gets processed by the owning thread.
     546*/
     547// static
     548QObject *QSelectThread::getTimerObject(int timerId)
     549{
     550    QMutexLocker locker(&mutex);
     551    Q_ASSERT(instance);
     552
     553    TimerInfo *t = instance->timers.value(timerId);
     554    if (t)
     555        return t->obj;
     556
     557    return 0;
     558}
     559
     560/*!
     561    Incrreases the usage count of the QSelectThread instance by one. If no
     562    QSelectThread instance exists yet, creates it. Note that the thread is
    410563    started on demand by addSelect(), not by this method.
    411564
     
    415568*/
    416569// static
    417 void QSockSelectThread::attachThread()
     570void QSelectThread::attachThread()
    418571{
    419572    QMutexLocker locker(&mutex);
    420573
    421574    if (instance == 0) {
    422         instance = new QSockSelectThread();
     575        instance = new QSelectThread();
    423576        instance->start();
    424577    }
     
    429582/*!
    430583    Removes all socket notifiers owned by the current thread and decreases the
    431     usage count of the QSockSelectThread instance by one. When the usage count
     584    usage count of the QSelectThread instance by one. When the usage count
    432585    goes to zero, the socket select thread is stopped and the instance is
    433586    deleted.
     
    437590*/
    438591// static
    439 void QSockSelectThread::detachThread()
     592void QSelectThread::detachThread()
    440593{
    441594    QMutexLocker locker(&mutex);
    442595    Q_ASSERT(instance);
    443596
     597
    444598    for (Sockets::iterator it = instance->sockets.begin();
    445599          it != instance->sockets.end();) {
    446600        QSocketNotifier *notifier = it.value();
    447601        if (notifier->thread() == QThread::currentThread()) {
    448             PendingOp op = {Remove, notifier->socket(), notifier->type()};
    449             instance->pending.append(op);
     602            PendingOp op = {Remove, notifier->socket(), notifier->type()};
     603            instance->pending.append(op);
    450604            it = instance->sockets.erase(it);
     605
     606
     607
     608
     609
     610
     611
     612
     613
     614
     615
     616
     617
     618
     619
     620
     621
     622
     623
    451624        } else {
    452625            ++it;
     
    464637    }
    465638}
    466 void QSockSelectThread::run()
     639
     640QSelectThread::QSelectThread() : finish(false), refcnt(0)
     641{
     642    // initialize socket stuff
     643    maxSockfd = -1;
     644
     645    // initialize timer stuff
     646    getTime(currentTime);
     647
     648    // initialize the timeChanged() machinery
     649    previousTime = currentTime;
     650
     651    tms unused;
     652    previousTicks = times(&unused);
     653
     654    ticksPerSecond = sysconf(_SC_CLK_TCK);
     655    msPerTick = 1000 / ticksPerSecond;
     656}
     657
     658QSelectThread::~QSelectThread()
     659{
     660    // detachThread() calls must clean up sockets/timers they own
     661    Q_ASSERT(sockets.isEmpty());
     662    Q_ASSERT(timers.isEmpty());
     663    Q_ASSERT(timersByTimeout.isEmpty());
     664
     665    // but, still, be nice and cleanup timers (we allocate them with new)
     666    qDeleteAll(timers);
     667}
     668
     669void QSelectThread::run()
    467670{
    468671    // maintain a separate hash for HWNDs to avoid mutex locking every time
     
    476679    FD_ZERO(&exS);
    477680
     681
     682
    478683    do {
    479         mutex.lock();
    480 
    481684        while (!finish && sockets.isEmpty()) {
    482685            cond.wait(&mutex);
    483686        }
    484687
    485         if (finish) {
    486             mutex.unlock();
     688        if (finish)
    487689            break;
    488         }
    489 
    490         while (!pending.isEmpty()) {
    491             PendingOp p = pending.takeFirst();
     690
     691        // process pending socket operations
     692        while (!pending.isEmpty()) {
     693            Pending.takeFirst();
    492694            switch (p.op) {
    493695                case Add:
     
    500702                            FD_SET(p.sockfd, &exS); break;
    501703                    }
    502                     hwnds.insert(toKey(p.sockfd, p.type), p.hwnd);
     704                    hwnds.insert(toKey(p.sockfd, p.type), p.hwnd);
    503705                    maxSockfd = qMax(maxSockfd, p.sockfd);
    504706                    break;
     
    512714                            FD_CLR(p.sockfd, &exS); break;
    513715                    }
    514                     hwnds.remove(toKey(p.sockfd, p.type));
     716                    hwnds.remove(toKey(p.sockfd, p.type));
    515717                    if (maxSockfd == p.sockfd) {
    516718                        // find the new hignest socket
     
    528730        }
    529731
     732
     733
     734
     735
     736
     737
     738
     739
    530740        // do select
    531         mutex.unlock();
    532         int nsel = ::select(maxSockfd + 1, &readS, &writeS, &exS, NULL);
     741        int nsel = ::select(maxSockfd + 1, &readS, &writeS, &exS, timeout);
    533742        if (nsel > 0) {
    534743            for (Hwnds::const_iterator it = hwnds.constBegin();
     
    536745                int sockfd = toSocket(it.key());
    537746                bool isSet = false;
    538                 switch (toType(it.key())) {
     747                switch (toType(it.key())) {
    539748                    case QSocketNotifier::Read:
    540749                        isSet = FD_ISSET(sockfd, &readS); break;
     
    548757            }
    549758        }
     759
     760
     761
     762
     763
     764
     765
    550766    } while(true);
    551 }
    552 
    553 // Must be called from under QSockSelectThread::mutex
    554 void QSockSelectThread::cancelSelectOrIdle()
     767
     768    mutex.unlock();
     769}
     770
     771// Must be called from under QSelectThread::mutex
     772void QSelectThread::cancelSelectOrIdle()
    555773{
    556774    if (maxSockfd >= 0) {
     
    563781}
    564782
     783
     784
     785
     786
     787
     788
     789
     790
     791
     792
     793
     794
     795
     796
     797
     798
     799
     800
     801
     802
     803
     804
     805
     806
     807
     808
     809
     810
     811
     812
     813
     814
     815
     816
     817
     818
     819
     820
     821
     822
     823
     824
     825
     826
     827
     828
     829
     830
     831
     832
     833
     834
     835
     836
     837
     838
     839
     840
     841
     842
     843
     844
     845
     846
     847
     848
     849
     850
     851
     852
     853
     854
     855
     856
     857
     858
     859
     860
     861
     862
     863
     864
     865
     866
     867
     868
     869
     870
     871
     872
     873
     874
     875
     876
     877
     878
     879
     880
     881
     882
     883
     884
     885
     886
     887
     888
     889
     890
     891
     892
     893
     894
     895
     896
     897
     898
     899
     900
     901
     902
     903
     904
     905
     906
     907
     908
     909
     910
     911
     912
     913
     914
     915
     916
     917
     918
     919
     920
     921
     922
     923
     924
     925
     926
     927
     928
     929
     930
     931
    565932#else
    566933
    567 class QSockSelectThread
    568 {
     934class QSelectThread
     935{
     936    // dummy implementation
     937
    569938public:
    570939    static void addSelect(QSocketNotifier *notifier, HWND hwnd) {
     
    577946    static QSocketNotifier *getSocketNotifier(int key); { return 0; }
    578947
     948
     949
     950
     951
     952
     953
     954
     955
     956
     957
     958
     959
     960
    579961    static void attachThread() {}
    580962    static void detachThread() {}
     
    593975    void createAuxWnd();
    594976
    595     // Auxiliary object window to process WM_U_SEM_SELECT and WM_TIMER messages.
     977    // Auxiliary object window to process WM_U_SEM_SELECT and WM_TIMER messages.
    596978    // We need a dedicated window along with processing these messages directly in
    597979    // QEventLoop::processEvents() to make sure they are processed even if the
     
    607989        MRESULT message(ULONG msg, MPARAM mp1, MPARAM mp2);
    608990        QEventDispatcherPMPrivate *dispatcher;
     991
     992
    609993    } auxWnd;
    610994
     
    615999
    6161000// @todo later
    617 //
    618 //  // timers
    619 //  WinTimerVec timerVec;
    620 //  WinTimerDict timerDict;
    621 //  void registerTimer(WinTimerInfo *t);
    622 //  void unregisterTimer(WinTimerInfo *t);
    623 //  void sendTimerEvent(int timerId);
    6241001//
    6251002//  QList<QMSG> queuedUserInputEvents;
     
    6851062        case WM_U_SEM_SELECT: {
    6861063            QSocketNotifier *notifier =
    687                 QSockSelectThread::getSocketNotifier(LONGFROMMP(mp1));
    688                 if (notifier) {
    689                     QEvent event(QEvent::SockAct);
    690                     QCoreApplication::sendEvent(notifier, &event);
    691                 }
     1064                QSelectThread::getSocketNotifier(LONGFROMMP(mp1));
     1065            if (notifier) {
     1066                QEvent event(QEvent::SockAct);
     1067                QCoreApplication::sendEvent(notifier, &event);
     1068            }
    6921069            break;
    6931070        }
    694         case WM_U_SEM_ZEROTIMER: {
    695 // @todo later
    696 //          if (numZeroTimers) {
    697 //              activateZeroTimers();
    698 //              // repost the message if there are still zero timers left
    699 //              if (numZeroTimers)
    700 //                  WinPostMsg(hwnd(), WM_U_SEM_ZEROTIMER, 0, 0);
    701 //          }
     1071        case WM_U_SEM_TIMER: {
     1072            int timerId = LONGFROMMP(mp1);
     1073            QObject *obj = QSelectThread::getTimerObject(timerId);
     1074
     1075            if (obj && !timersInSend.contains(timerId)) {
     1076                // send event, but don't allow it to recurse
     1077                timersInSend += timerId;
     1078
     1079                QTimerEvent e(timerId);
     1080                QCoreApplication::sendEvent(obj, &e);
     1081
     1082                timersInSend -= timerId;
     1083            }
    7021084            break;
    7031085        }
    704         case WM_TIMER: {
    705 // @todo later
    706 //          USHORT id = SHORT1FROMMP(mp1);
    707 //          dispatchTimer((uint) id, &qmsg);
     1086        default:
    7081087            break;
    709         }
    7101088    }
    7111089
    7121090    return FALSE;
    7131091}
    714 
    715 // @todo remove
    716 #if 0
    717 
    718 LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
    719 {
    720     if (message == WM_NCCREATE) {
    721             return true;
    722     } else if (message == WM_USER) {
    723 
    724         // socket notifier message
    725         MSG msg;
    726         msg.hwnd = hwnd;
    727         msg.message = message;
    728         msg.wParam = wp;
    729         msg.lParam = lp;
    730 
    731         QCoreApplication *app = QCoreApplication::instance();
    732         long result;
    733         if (app && app->filterEvent(&msg, &result))
    734             return result;
    735 
    736         int type = -1;
    737         switch (WSAGETSELECTEVENT(lp)) {
    738         case FD_READ:
    739         case FD_CLOSE:
    740         case FD_ACCEPT:
    741             type = 0;
    742             break;
    743         case FD_WRITE:
    744         case FD_CONNECT:
    745             type = 1;
    746             break;
    747         case FD_OOB:
    748             type = 2;
    749             break;
    750         }
    751         if (type >= 0) {
    752 
    753     #ifdef GWLP_USERDATA
    754             QEventDispatcherPM *eventDispatcher =
    755                 (QEventDispatcherPM *) GetWindowLongPtrA(hwnd, GWLP_USERDATA);
    756     #else
    757             QEventDispatcherPM *eventDispatcher =
    758                 (QEventDispatcherPM *) GetWindowLongA(hwnd, GWL_USERDATA);
    759     #endif
    760             if (eventDispatcher) {
    761                 QEventDispatcherPMPrivate *d = eventDispatcher->d_func();
    762                 QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
    763                 QSNDict *dict = sn_vec[type];
    764 
    765                 QSockNot *sn = dict ? dict->value(wp) : 0;
    766                 if (sn) {
    767                     QEvent event(QEvent::SockAct);
    768                     QCoreApplication::sendEvent(sn->obj, &event);
    769                 }
    770             }
    771         }
    772         return 0;
    773 
    774     } else if (message == WM_TIMER) {
    775 
    776         MSG msg;
    777         msg.hwnd = hwnd;
    778         msg.message = message;
    779         msg.wParam = wp;
    780         msg.lParam = lp;
    781 
    782         QCoreApplication *app = QCoreApplication::instance();
    783         Q_ASSERT_X(app, "qt_interal_proc", "Timer fired, but no QCoreApplication");
    784         if (!app) {
    785             KillTimer(hwnd, wp);
    786             return 0;
    787         }
    788 
    789         long result;
    790         if (app->filterEvent(&msg, &result))
    791             return result;
    792 
    793         QEventDispatcherPM *eventDispatcher =
    794             qobject_cast<QEventDispatcherPM *>(QAbstractEventDispatcher::instance());
    795         Q_ASSERT(eventDispatcher != 0);
    796         QEventDispatcherPMPrivate *d = eventDispatcher->d_func();
    797         d->sendTimerEvent(wp);
    798         return 0;
    799     }
    800 
    801     return  DefWindowProc(hwnd, message, wp, lp);
    802 }
    803 
    804 void QEventDispatcherPMPrivate::registerTimer(WinTimerInfo *t)
    805 {
    806     Q_ASSERT(internalHwnd);
    807 
    808     Q_Q(QEventDispatcherPM);
    809 
    810     int ok = 0;
    811 
    812     if (t->interval > 10 || !t->interval || !qtimeSetEvent) {
    813         ok = 1;
    814         if (!t->interval)  // optimization for single-shot-zero-timer
    815             QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId));
    816         else
    817             ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
    818     } else {
    819         ok = t->fastTimerId = qtimeSetEvent(t->interval, 1, qt_fast_timer_proc, (DWORD_PTR)t,
    820                                             TIME_CALLBACK_FUNCTION | TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
    821         if (ok == 0) { // fall back to normal timer if no more multimedia timers avaiable
    822             ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
    823         }
    824     }
    825 
    826     if (ok == 0)
    827         qErrnoWarning("QEventDispatcherPM::registerTimer: Failed to create a timer");
    828 }
    829 
    830 void QEventDispatcherPMPrivate::unregisterTimer(WinTimerInfo *t)
    831 {
    832     // mark timer as unused
    833     if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent)
    834         QAbstractEventDispatcherPrivate::releaseTimerId(t->timerId);
    835 
    836     if (t->interval == 0) {
    837         QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
    838     } else if (t->fastTimerId != 0) {
    839         qtimeKillEvent(t->fastTimerId);
    840         QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
    841     } else if (internalHwnd) {
    842         KillTimer(internalHwnd, t->timerId);
    843     }
    844     delete t;
    845 }
    846 
    847 void QEventDispatcherPMPrivate::sendTimerEvent(int timerId)
    848 {
    849     WinTimerInfo *t = timerDict.value(timerId);
    850     if (t && !t->inTimerEvent) {
    851         // send event, but don't allow it to recurse
    852         t->inTimerEvent = true;
    853 
    854         QTimerEvent e(t->timerId);
    855         QCoreApplication::sendEvent(t->obj, &e);
    856 
    857         // timer could have been removed
    858         t = timerDict.value(timerId);
    859         if (t) {
    860             t->inTimerEvent = false;
    861         }
    862     }
    863 }
    864 
    865 void QEventDispatcherPM::createInternalHwnd()
    866 {
    867     Q_D(QEventDispatcherPM);
    868 
    869     Q_ASSERT(!d->internalHwnd);
    870     if (d->internalHwnd)
    871         return;
    872     d->internalHwnd = qt_create_internal_window(this);
    873 
    874     // register all socket notifiers
    875     QList<int> sockets = (d->sn_read.keys().toSet()
    876                           + d->sn_write.keys().toSet()
    877                           + d->sn_except.keys().toSet()).toList();
    878     for (int i = 0; i < sockets.count(); ++i)
    879         d->doWsaAsyncSelect(sockets.at(i));
    880 
    881     // start all normal timers
    882     for (int i = 0; i < d->timerVec.count(); ++i)
    883         d->registerTimer(d->timerVec.at(i));
    884 }
    885 
    886 #endif
    8871092
    8881093QEventDispatcherPM::QEventDispatcherPM(QObject *parent)
     
    10221227    d->createAuxWnd();
    10231228
    1024     QSockSelectThread::addSelect(notifier, d->auxWnd.hwnd());
     1229    QSelectThread::addSelect(notifier, d->auxWnd.hwnd());
    10251230}
    10261231
     
    10411246#endif
    10421247
    1043     QSockSelectThread::removeSelect(notifier);
     1248    QSelectThread::removeSelect(notifier);
    10441249}
    10451250
    10461251void QEventDispatcherPM::registerTimer(int timerId, int interval, QObject *object)
    10471252{
    1048 // @todo later
    1049 #if 0
     1253#ifndef QT_NO_DEBUG
    10501254    if (timerId < 1 || interval < 0 || !object) {
    10511255        qWarning("QEventDispatcherPM::registerTimer: invalid arguments");
     
    10551259        return;
    10561260    }
     1261
    10571262
    10581263    Q_D(QEventDispatcherPM);
    1059 
    1060     register WinTimerInfo *t = new WinTimerInfo;
    1061     t->dispatcher = this;
    1062     t->timerId  = timerId;
    1063     t->interval = interval;
    1064     t->obj  = object;
    1065     t->inTimerEvent = false;
    1066     t->fastTimerId = 0;
    1067 
    1068     if (d->internalHwnd)
    1069         d->registerTimer(t);
    1070 
    1071     d->timerVec.append(t);                      // store in timer vector
    1072     d->timerDict.insert(t->timerId, t);          // store timers in dict
    1073 #endif
     1264    d->createAuxWnd();
     1265
     1266    QSelectThread::addTimer(timerId, interval, object, d->auxWnd.hwnd());
    10741267}
    10751268
    10761269bool QEventDispatcherPM::unregisterTimer(int timerId)
    10771270{
    1078 // @todo later
    1079 #if 0
     1271#ifndef QT_NO_DEBUG
    10801272    if (timerId < 1) {
    10811273        qWarning("QEventDispatcherPM::unregisterTimer: invalid argument");
    10821274        return false;
    1083     }
    1084     QThread *currentThread = QThread::currentThread();
    1085     if (thread() != currentThread) {
     1275    } else if (thread() != QThread::currentThread()) {
    10861276        qWarning("QObject::killTimer: timers cannot be stopped from another thread");
    10871277        return false;
    10881278    }
    1089 
    1090     Q_D(QEventDispatcherPM);
    1091     if (d->timerVec.isEmpty() || timerId <= 0)
    1092         return false;
    1093 
    1094     WinTimerInfo *t = d->timerDict.value(timerId);
    1095     if (!t)
    1096         return false;
    1097 
    1098     d->timerDict.remove(t->timerId);
    1099     d->timerVec.removeAll(t);
    1100     d->unregisterTimer(t);
    1101     return true;
    1102 #else
    1103     return false;
    11041279#endif
     1280
     1281
    11051282}
    11061283
    11071284bool QEventDispatcherPM::unregisterTimers(QObject *object)
    11081285{
    1109 // @todo later
    1110 #if 0
     1286#ifndef QT_NO_DEBUG
    11111287    if (!object) {
    11121288        qWarning("QEventDispatcherPM::unregisterTimers: invalid argument");
    11131289        return false;
    1114     }
    1115     QThread *currentThread = QThread::currentThread();
    1116     if (object->thread() != thread() || thread() != currentThread) {
     1290    } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
    11171291        qWarning("QObject::killTimers: timers cannot be stopped from another thread");
    11181292        return false;
    11191293    }
    1120 
    1121     Q_D(QEventDispatcherPM);
    1122     if (d->timerVec.isEmpty())
    1123         return false;
    1124     register WinTimerInfo *t;
    1125     for (int i=0; i<d->timerVec.size(); i++) {
    1126         t = d->timerVec.at(i);
    1127         if (t && t->obj == object) {                // object found
    1128             d->timerDict.remove(t->timerId);
    1129             d->timerVec.removeAt(i);
    1130             d->unregisterTimer(t);
    1131             --i;
    1132         }
    1133     }
    1134     return true;
    1135 #else
    1136     return false;
    11371294#endif
     1295
     1296
    11381297}
    11391298
     
    11411300QEventDispatcherPM::registeredTimers(QObject *object) const
    11421301{
    1143 // @todo later
    1144 #if 0
     1302#ifndef QT_NO_DEBUG
    11451303    if (!object) {
    11461304        qWarning("QEventDispatcherPM:registeredTimers: invalid argument");
    11471305        return QList<TimerInfo>();
    11481306    }
    1149 
    1150     Q_D(const QEventDispatcherPM);
    1151     QList<TimerInfo> list;
    1152     for (int i = 0; i < d->timerVec.size(); ++i) {
    1153         const WinTimerInfo *t = d->timerVec.at(i);
    1154         if (t && t->obj == object)
    1155             list << TimerInfo(t->timerId, t->interval);
    1156     }
    1157     return list;
    1158 #else
    1159     return QList<TimerInfo>();
    11601307#endif
     1308
     1309
    11611310}
    11621311
     
    11851334void QEventDispatcherPM::startingUp()
    11861335{
    1187     QSockSelectThread::attachThread();
     1336    QSelectThread::attachThread();
    11881337}
    11891338
    11901339void QEventDispatcherPM::closingDown()
    11911340{
    1192     QSockSelectThread::detachThread();
    1193 
    1194 // @todo remove later
    1195 #if 0
    1196     Q_D(QEventDispatcherPM);
    1197 
    1198     // clean up any timers
    1199     while (!d->timerDict.isEmpty())
    1200         unregisterTimer((*(d->timerDict.begin()))->timerId);
    1201 #endif
    1202 }
    1203 
    1204 // @todo remove later
    1205 #if 0
    1206 bool QEventDispatcherPM::event(QEvent *e)
    1207 {
    1208     Q_D(QEventDispatcherPM);
    1209     if (e->type() == QEvent::ZeroTimerEvent) {
    1210         QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
    1211         WinTimerInfo *t = d->timerDict.value(zte->timerId());
    1212         if (t) {
    1213             t->inTimerEvent = true;
    1214 
    1215             QTimerEvent te(zte->timerId());
    1216             QCoreApplication::sendEvent(t->obj, &te);
    1217 
    1218             t = d->timerDict.value(zte->timerId());
    1219             if (t) {
    1220                 if (t->interval == 0 && t->inTimerEvent) {
    1221                     // post the next zero timer event as long as the timer was not restarted
    1222                     QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId()));
    1223                 }
    1224 
    1225                 t->inTimerEvent = false;
    1226             }
    1227         }
    1228         return true;
    1229     } else if (e->type() == QEvent::Timer) {
    1230         QTimerEvent *te = static_cast<QTimerEvent*>(e);
    1231         d->sendTimerEvent(te->timerId());
    1232     }
    1233     return QAbstractEventDispatcher::event(e);
    1234 }
    1235 #endif
     1341    QSelectThread::detachThread();
     1342}
    12361343
    12371344QT_END_NAMESPACE
  • trunk/src/corelib/kernel/qeventdispatcher_pm_p.h

    r67 r84  
    9191    void startingUp();
    9292    void closingDown();
    93 
    94 // @todo remove later
    95 //  bool event(QEvent *e);
    9693};
    9794
Note: See TracChangeset for help on using the changeset viewer.