Changeset 175
- Timestamp:
- Sep 9, 2009, 10:02:31 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/corelib/kernel/qeventdispatcher_pm.cpp
r161 r175 235 235 } 236 236 237 inline bool operator>=(const timeval &t1, const timeval &t2) 238 { 239 return !operator<(t1, t2); 240 } 241 237 242 inline timeval &operator+=(timeval &t1, const timeval &t2) 238 243 { … … 286 291 static bool removeTimers(QObject *object); 287 292 static QList<QPair<int, int> > knownTimers(QObject *object); 288 static QObject *getTimerObject(int timerId );293 static QObject *getTimerObject(int timerId, bool reset); 289 294 290 295 static void attachThread(); … … 340 345 QObject *obj; // - object to receive event 341 346 HWND hwnd; // - where to post the timer message 347 bool posted; // - true if a message has been posted 342 348 }; 343 349 … … 347 353 typedef QMap<timeval, TimerInfo*> TimevalMap; 348 354 TimevalMap timersByTimeout; 355 bool allTimersPosted; 349 356 350 357 timeval currentTime; … … 463 470 t->obj = object; 464 471 t->hwnd = hwnd; 472 t->posted = false; 465 473 466 474 instance->timers.insert(t->id, t); … … 546 554 that owns the timer (creates/registers/unregisters it). 547 555 556 If @a reset is true, the method also resets the 'posted' flag so that a 557 message for it may be posted again by the select thread. 558 548 559 May return 0 if the timer is stopped/deleted after WM_U_SEM_TIMER was issued 549 560 for it but before this message gets processed by the owning thread. 550 561 */ 551 562 // static 552 QObject *QSelectThread::getTimerObject(int timerId )563 QObject *QSelectThread::getTimerObject(int timerId, bool reset) 553 564 { 554 565 QMutexLocker locker(&mutex); … … 556 567 557 568 TimerInfo *t = instance->timers.value(timerId); 558 if (t) 569 if (t) { 570 if (reset) { 571 t->posted = false; 572 if (instance->allTimersPosted) { 573 // the select thread's been sleeping forever; wake it up -- we 574 // now have at least one timer that can be posted again 575 instance->allTimersPosted = false; 576 instance->cancelSelectOrIdle(); 577 } else { 578 // also wake it up if this timer was skipped when choosing the 579 // shortest wait interval so that a longer once could be chosen 580 bool haveNonPosted = false; 581 for (TimevalMap::const_iterator it = instance->timersByTimeout.begin(); 582 it != instance->timersByTimeout.end() && !haveNonPosted && 583 it.value() != t; 584 ++it) { 585 if (!it.value()->posted) 586 haveNonPosted = true; 587 } 588 if (!haveNonPosted) 589 instance->cancelSelectOrIdle(); 590 } 591 } 559 592 return t->obj; 593 } 560 594 561 595 return 0; … … 656 690 } 657 691 658 QSelectThread::QSelectThread() : finish(false), refcnt(0), cancelWait(false) 692 QSelectThread::QSelectThread() 693 : finish(false), refcnt(0), cancelWait(false), allTimersPosted(false) 659 694 { 660 695 // initialize socket stuff … … 771 806 mutex.lock(); 772 807 } else { 773 ulong msecs = timeout ? 774 timeout->tv_sec * 1000 + timeout->tv_usec / 1000 : ULONG_MAX; 775 nsel = -1; // cause to avoid activateTimers() when cancelled 808 nsel = -1; 809 errno = EINTR; 776 810 if (!cancelWait) { 811 long msecs = timeout ? 812 timeout->tv_sec * 1000l + timeout->tv_usec / 1000l : LONG_MAX; 777 813 if (!cond.wait(&mutex, msecs)) 778 814 nsel = 0; // indicate timeout … … 781 817 } 782 818 783 if (nsel == 0) { 784 // timeout, check if there are expired timers 819 if (nsel == 0 || (nsel == -1 && errno == EINTR)) { 820 // interrupt or timeout; check if there are expired or processed 821 // timers 785 822 activateTimers(); 786 823 } … … 892 929 893 930 /* 894 Returns the time to wait for the next timer, or null if no timers895 arewaiting.931 Returns the time to wait for the next timer, or false if no timers are 932 waiting. 896 933 */ 897 934 bool QSelectThread::timerWait(timeval &tm) … … 902 939 return false; 903 940 904 TimerInfo *t = timersByTimeout.begin().value(); // first waiting timer 941 // find first waiting timer with posted flag reset 942 TimevalMap::iterator it = timersByTimeout.begin(); 943 while (it.value()->posted && it != timersByTimeout.end()) 944 ++it; 945 if (it == timersByTimeout.end()) { 946 // all timers've been posted but not yet processed by the target window; 947 // set a flag to make sure the first getTimerObject(...,true) call will 948 // interrupt the indefinte wait we are about to enter 949 allTimersPosted = true; 950 return false; 951 } 952 953 TimerInfo *t = it.value(); 905 954 if (currentTime < t->timeout) { 906 955 // time to wait … … 925 974 updateCurrentTime(); 926 975 927 while(true) { 928 TimerInfo *t = timersByTimeout.begin().value(); 976 TimevalMap::iterator it = timersByTimeout.begin(); 977 978 while (it != timersByTimeout.end()) { 979 TimerInfo *t = it.value(); 929 980 930 981 if (currentTime < t->timeout) 931 982 break; // no timer has expired 932 983 984 if (t->posted) { 985 // ignore the timer since we already posted it 986 ++ it; 987 continue; 988 } 989 933 990 // remove from map 934 timersByTimeout.erase( timersByTimeout.begin());935 936 // determine next timeout time 991 timersByTimeout.erase(it); 992 993 // determine next timeout time after currentTime 937 994 if (t->interval.tv_sec == 0 && t->interval.tv_usec == 0) { 938 // zero timer; make sure it won't fire again in this loop 939 t->timeout.tv_sec = 0; 940 t->timeout.tv_usec = 1; 941 t->timeout += currentTime; 995 // zero timer 996 t->timeout = currentTime; 942 997 } else { 943 // normal timer; also make sure it won't fire again in this loop 944 t->timeout += t->interval; 945 if (t->timeout < currentTime) 946 t->timeout = currentTime + t->interval; 947 } 998 register qint64 time = t->timeout.tv_sec * 1000ll + t->timeout.tv_usec / 1000ll; 999 register qint64 curr = currentTime.tv_sec * 1000ll + currentTime.tv_usec / 1000ll; 1000 register qint64 ival = t->interval.tv_sec * 1000ll + t->interval.tv_usec / 1000ll; 1001 curr += (ival - ((curr - time) % ival)); 1002 t->timeout.tv_sec = curr / 1000ll; 1003 t->timeout.tv_usec = (curr % 1000ll) * 1000ll; 1004 } 1005 1006 // set the posted flag to avoid polluting the message queue with timer 1007 // messages if the target window is not fast enough to process them 1008 t->posted = true; 948 1009 949 1010 // reinsert timer (in proper sort order) … … 952 1013 // post the timer message 953 1014 WinPostMsg(t->hwnd, WM_U_SEM_TIMER, MPFROMLONG(t->id), 0); 1015 1016 // start over 1017 it = timersByTimeout.begin(); 954 1018 } 955 1019 … … 984 1048 return QList<QPair<int, int> >(); 985 1049 } 986 static QObject *getTimerObject(int timerId );1050 static QObject *getTimerObject(int timerId, bool reset); 987 1051 988 1052 static void attachThread() {} … … 1092 1156 case WM_U_SEM_TIMER: { 1093 1157 int timerId = LONGFROMMP(mp1); 1094 QObject *obj = QSelectThread::getTimerObject(timerId );1158 QObject *obj = QSelectThread::getTimerObject(timerId, true /*reset*/); 1095 1159 1096 1160 if (obj && !timersInSend.contains(timerId)) {
Note:
See TracChangeset
for help on using the changeset viewer.