- Timestamp:
- Sep 30, 2009, 6:08:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/corelib/kernel/qeventdispatcher_pm.cpp
r175 r196 284 284 static void addSelect(QSocketNotifier *notifier, HWND hwnd); 285 285 static void removeSelect(QSocketNotifier *notifier); 286 static QSocketNotifier *getSocketNotifier(int key );286 static QSocketNotifier *getSocketNotifier(int key, bool reset); 287 287 288 288 // timer support is based on QTimerInfoList from the Unix implementation … … 300 300 ~QSelectThread(); 301 301 302 enum Op { Add, Remove }; 303 void updateMaxSockFd(int sockFd, Op op); 304 fd_set *setForType(QSocketNotifier::Type type); 305 302 306 void run(); 303 307 void cancelSelectOrIdle(); … … 322 326 // socket stuff 323 327 324 typedef QHash<int, QSocketNotifier*> Sockets; 328 typedef QPair<QSocketNotifier*, HWND> SockNot; 329 typedef QHash<int, SockNot> Sockets; 325 330 Sockets sockets; 331 332 fd_set readS, writeS, exS; 326 333 int maxSockfd; 327 328 enum Op { Add, Remove };329 struct PendingSockOp {330 Op op;331 int sockfd;332 Type type;333 HWND hwnd;334 };335 336 typedef QList<PendingSockOp> PendingSockets;337 PendingSockets pendingSockets;338 334 339 335 // timer stuff … … 402 398 403 399 } 404 instance->sockets.insert(key, notifier);405 PendingSockOp op = {Add, sockfd, type, hwnd};406 instance-> pendingSockets.append(op);400 instance->sockets.insert(key, qMakePair(notifier, hwnd)); 401 FD_SET(sockfd, instance->setForType(type)); 402 instance->updateMaxSockFd(sockfd, Add); 407 403 instance->cancelSelectOrIdle(); 408 404 } … … 420 416 if (instance->sockets.contains(key)) { 421 417 instance->sockets.remove(key); 422 PendingSockOp op = {Remove, sockfd, type};423 instance-> pendingSockets.append(op);418 FD_CLR(sockfd, instance->setForType(type)); 419 instance->updateMaxSockFd(sockfd, Remove); 424 420 instance->cancelSelectOrIdle(); 425 421 } … … 436 432 */ 437 433 // static 438 QSocketNotifier *QSelectThread::getSocketNotifier(int key )434 QSocketNotifier *QSelectThread::getSocketNotifier(int key, bool reset) 439 435 { 440 436 QMutexLocker locker(&mutex); 441 437 Q_ASSERT(instance); 442 438 443 if (instance->sockets.contains(key) && 444 instance->sockets[key]->thread() == QThread::currentThread()) 445 return instance->sockets[key]; 439 if (instance->sockets.contains(key)) { 440 QSocketNotifier* notifier = instance->sockets[key].first; 441 if (notifier->thread() == QThread::currentThread()) { 442 if (reset && notifier->isEnabled()) { 443 // add the socket back to the set 444 int sockfd = notifier->socket(); 445 fd_set *set = instance->setForType(notifier->type()); 446 FD_SET(sockfd, set); 447 instance->updateMaxSockFd(sockfd, Add); 448 // inform the select thread that this socket may be included 449 // in the set and posted again 450 instance->cancelSelectOrIdle(); 451 } 452 return notifier; 453 } 454 } 446 455 447 456 return 0; … … 577 586 } else { 578 587 // also wake it up if this timer was skipped when choosing the 579 // shortest wait interval so that a longer on ce could be chosen588 // shortest wait interval so that a longer one could be chosen 580 589 bool haveNonPosted = false; 581 590 for (TimevalMap::const_iterator it = instance->timersByTimeout.begin(); … … 647 656 for (Sockets::iterator it = instance->sockets.begin(); 648 657 it != instance->sockets.end();) { 649 QSocketNotifier *notifier = it.value() ;658 QSocketNotifier *notifier = it.value().first; 650 659 if (notifier->thread() == QThread::currentThread()) { 651 PendingSockOp op = {Remove, notifier->socket(), notifier->type()};652 instance->pendingSockets.append(op);653 660 it = instance->sockets.erase(it); 661 instance->updateMaxSockFd(notifier->socket(), Remove); 662 FD_CLR(notifier->socket(), instance->setForType(notifier->type())); 654 663 } else { 655 664 ++it; … … 694 703 { 695 704 // initialize socket stuff 705 FD_ZERO(&readS); 706 FD_ZERO(&writeS); 707 FD_ZERO(&exS); 696 708 maxSockfd = -1; 697 709 … … 720 732 } 721 733 734 // Finds the new highest socket FD. Must be called from under the mutex. 735 void QSelectThread::updateMaxSockFd(int sockFd, Op op) 736 { 737 switch (op) { 738 case Add: 739 maxSockfd = qMax(maxSockfd, sockFd); 740 break; 741 case Remove: 742 if (maxSockfd == sockFd) { 743 maxSockfd = -1; 744 if (!sockets.isEmpty()) { 745 for (Sockets::const_iterator it = sockets.constBegin(); 746 it != sockets.constEnd(); ++it) { 747 maxSockfd = qMax(toSocket(it.key()), maxSockfd); 748 } 749 } 750 } 751 break; 752 } 753 } 754 755 // Returns the set corresponding to the socket type. Must be called from under 756 // the mutex. 757 fd_set *QSelectThread::setForType(QSocketNotifier::Type type) 758 { 759 fd_set *set = 0; 760 switch (type) { 761 case QSocketNotifier::Read: 762 set = &readS; break; 763 case QSocketNotifier::Write: 764 set = &writeS; break; 765 case QSocketNotifier::Exception: 766 set = &exS; break; 767 } 768 return set; 769 } 770 722 771 void QSelectThread::run() 723 772 { 724 // maintain a separate hash for HWNDs to avoid mutex locking every time725 // select() returns an event that we want to post726 typedef QHash<int, HWND> Hwnds;727 Hwnds hwnds;728 729 fd_set readS, writeS, exS;730 FD_ZERO(&readS);731 FD_ZERO(&writeS);732 FD_ZERO(&exS);733 734 773 mutex.lock(); 735 774 736 775 do { 737 // process pending socket operations738 while (!pendingSockets.isEmpty()) {739 PendingSockOp p = pendingSockets.takeFirst();740 switch (p.op) {741 case Add:742 switch (p.type) {743 case QSocketNotifier::Read:744 FD_SET(p.sockfd, &readS); break;745 case QSocketNotifier::Write:746 FD_SET(p.sockfd, &writeS); break;747 case QSocketNotifier::Exception:748 FD_SET(p.sockfd, &exS); break;749 }750 hwnds.insert(toSockKey(p.sockfd, p.type), p.hwnd);751 maxSockfd = qMax(maxSockfd, p.sockfd);752 break;753 case Remove:754 switch (p.type) {755 case QSocketNotifier::Read:756 FD_CLR(p.sockfd, &readS); break;757 case QSocketNotifier::Write:758 FD_CLR(p.sockfd, &writeS); break;759 case QSocketNotifier::Exception:760 FD_CLR(p.sockfd, &exS); break;761 }762 hwnds.remove(toSockKey(p.sockfd, p.type));763 if (maxSockfd == p.sockfd) {764 // find the new hignest socket765 maxSockfd = -1;766 if (!hwnds.isEmpty()) {767 for (Hwnds::const_iterator it = hwnds.constBegin();768 it != hwnds.constEnd(); ++it) {769 maxSockfd = qMax(toSocket(it.key()), maxSockfd);770 }771 }772 }773 break;774 }775 }776 777 776 // get the maximum time we can wait (for the closest timer) 778 777 timeval *timeout = 0; … … 787 786 mutex.unlock(); 788 787 nsel = ::select(maxSockfd + 1, &tmpRead, &tmpWrite, &tmpEx, timeout); 788 mutex.lock(); 789 789 if (nsel > 0) { 790 for (Hwnds::const_iterator it = hwnds.constBegin(); 791 it != hwnds.constEnd(); ++it) { 790 // find out which sockets to post. Note that we remove these 791 // sockets from the main sets to avoid polluting the message 792 // queue with sockett messages if the target window is not fast 793 // enough to process them. They will be put back once processed. 794 for (Sockets::const_iterator it = sockets.constBegin(); 795 it != sockets.constEnd(); ++it) { 792 796 int sockfd = toSocket(it.key()); 797 Type type = toSockType(it.key()); 793 798 bool isSet = false; 794 switch (t oSockType(it.key())) {799 switch (type) { 795 800 case QSocketNotifier::Read: 796 801 isSet = FD_ISSET(sockfd, &tmpRead); break; … … 800 805 isSet = FD_ISSET(sockfd, &tmpEx); break; 801 806 } 802 if (isSet) 803 WinPostMsg(it.value(), WM_U_SEM_SELECT, MPFROMLONG(it.key()), 0); 807 if (isSet) { 808 fd_set *set = setForType(type); 809 FD_CLR(sockfd, set); 810 updateMaxSockFd(sockfd, Remove); 811 WinPostMsg(it.value().second, WM_U_SEM_SELECT, MPFROMLONG(it.key()), 0); 812 } 804 813 } 805 814 } 806 mutex.lock();807 815 } else { 808 816 nsel = -1; … … 1035 1043 } 1036 1044 static void removeSelect(QSocketNotifier *notifier) {} 1037 static QSocketNotifier *getSocketNotifier(int key ); { return 0; }1045 static QSocketNotifier *getSocketNotifier(int key, bool reset); { return 0; } 1038 1046 1039 1047 static void addTimer(int timerId, int interval, QObject *object, HWND hwnd) { … … 1147 1155 case WM_U_SEM_SELECT: { 1148 1156 QSocketNotifier *notifier = 1149 QSelectThread::getSocketNotifier(LONGFROMMP(mp1) );1157 QSelectThread::getSocketNotifier(LONGFROMMP(mp1), true /*reset*/); 1150 1158 if (notifier) { 1151 1159 QEvent event(QEvent::SockAct);
Note:
See TracChangeset
for help on using the changeset viewer.