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 238 239 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); 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 342 348 }; 343 349 … … 347 353 typedef QMap<timeval, TimerInfo*> TimevalMap; 348 354 TimevalMap timersByTimeout; 355 349 356 350 357 timeval currentTime; … … 463 470 t->obj = object; 464 471 t->hwnd = hwnd; 472 465 473 466 474 instance->timers.insert(t->id, t); … … 546 554 that owns the timer (creates/registers/unregisters it). 547 555 556 557 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) 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 812 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 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 985 986 987 988 989 933 990 // remove from map 934 timersByTimeout.erase( timersByTimeout.begin());935 936 // determine next timeout time 991 timersByTimeout.erase(); 992 993 // determine next timeout time 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 1017 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); 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); 1095 1159 1096 1160 if (obj && !timersInSend.contains(timerId)) {
Note:
See TracChangeset
for help on using the changeset viewer.