Changeset 116
- Timestamp:
- Aug 11, 2006, 3:01:59 PM (19 years ago)
- Location:
- trunk/src/kernel
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel/qeventloop_p.h
r8 r116 70 70 int fd; 71 71 fd_set *queue; 72 #if defined(Q_WS_PM) 73 fd_set *active; 74 #endif 72 75 }; 73 76 … … 132 135 // highest fd for all socket notifiers 133 136 int sn_highest; 137 #if defined(Q_WS_PM) 138 // fd for cancelling select() 139 int sn_cancel; 140 #endif 134 141 // 3 socket notifier types - read, write and exception 135 142 QSockNotType sn_vec[3]; -
trunk/src/kernel/qeventloop_pm.cpp
r113 r116 658 658 static QSemaphore ss_flag( 1 ); 659 659 660 // Note: must be called from under ss_mutex lock! 661 static inline void find_highest_fd( QEventLoopPrivate *d ) 662 { 663 d->sn_highest = -1; 664 for ( int i = 0; i < 3; i ++ ) { 665 QPtrList<QSockNot> *list = d->sn_vec[i].list; 666 if ( list && !list->isEmpty() ) { 667 QSockNot *sn = list->first(); 668 while ( sn && !FD_ISSET( sn->fd, sn->active ) ) 669 sn = list->next(); 670 if ( sn ) 671 d->sn_highest = QMAX( d->sn_highest, // list is fd-sorted 672 sn->fd ); 673 } 674 } 675 } 676 660 677 void QSockSelectThread::run() 661 678 { … … 680 697 // do select 681 698 int nfds = d->sn_highest + 1; 699 d->sn_cancel = d->sn_highest; 682 700 ss_mutex.unlock(); 683 701 int nsel = ::select( nfds, … … 690 708 // if select says data is ready on any socket, then set 691 709 // the socket notifier to pending 692 int i;693 for ( i =0; i<3; i++ ) {710 bool activate = FALSE; 711 for ( int i = 0; i < 3; i++ ) { 694 712 if ( ! d->sn_vec[i].list ) 695 713 continue; … … 698 716 while ( sn ) { 699 717 if ( FD_ISSET( sn->fd, &d->sn_vec[i].select_fds ) ) { 700 // see comments in sideQEventLoop::setSocketNotifierPending()718 // see comments in QEventLoop::setSocketNotifierPending() 701 719 if ( !FD_ISSET( sn->fd, sn->queue ) ) { 720 // queue the socket activation 702 721 d->sn_pending_list.insert( 703 722 (rand() & 0xff) % (d->sn_pending_list.count()+1), 704 sn 705 ); 723 sn ); 706 724 FD_SET( sn->fd, sn->queue ); 725 // remove from enabled sockets to prevent deadlocks 726 // on blocking sockets (and to reduce CPU load caused 727 // by frequent select() calls) when the event queue 728 // is not processed fast enough to handle activation 729 FD_CLR( sn->fd, sn->active ); 730 if ( sn->fd == d->sn_highest ) 731 find_highest_fd( d ); 732 activate = TRUE; 707 733 } 708 734 } … … 711 737 } 712 738 ss_mutex.unlock(); 713 // post a message to activate socket notifiers 714 qt_aux_win.post( WM_U_SEM_SELECT, 0, 0 ); 739 // post a message to activate socket notifiers 740 if ( activate ) 741 qt_aux_win.post( WM_U_SEM_SELECT, 0, 0 ); 715 742 } 716 743 } else { 744 d->sn_cancel = -1; 717 745 // no sockets to select(), go to the idle state 718 746 ss_mutex.unlock(); … … 730 758 ss_mutex.lock(); 731 759 exit = terminate; 732 if ( d->sn_ highest>= 0 ) {760 if ( d->sn_cancel >= 0 ) { 733 761 // terminate select() execution 734 ::so_cancel( d->sn_ highest);762 ::so_cancel( d->sn_cancel ); 735 763 } else { 736 764 // terminate the idle state by releasing the flag … … 768 796 { 769 797 d->sn_highest = -1; 798 d->sn_cancel = -1; 770 799 771 800 qt_ensure_pm(); … … 855 884 QMutexLocker locker( &ss_mutex ); 856 885 ss_thread->cancelSelectOrIdle(); 857 886 858 887 QPtrList<QSockNot> *list = d->sn_vec[type].list; 859 fd_set *fds = &d->sn_vec[type].enabled_fds;860 888 QSockNot *sn; 861 889 … … 873 901 sn->fd = sockfd; 874 902 sn->queue = &d->sn_vec[type].pending_fds; 903 sn->active = &d->sn_vec[type].enabled_fds; 875 904 876 905 if ( list->isEmpty() ) { … … 893 922 } 894 923 895 FD_SET( sockfd, fds ); 896 d->sn_highest = QMAX( d->sn_highest, sockfd ); 924 // enable the socket only if it's not already pending 925 if ( !FD_ISSET( sockfd, sn->queue ) ) { 926 FD_SET( sockfd, sn->active ); 927 d->sn_highest = QMAX( d->sn_highest, sockfd ); 928 } 897 929 #endif // QT_THREAD_SUPPORT 898 930 } … … 921 953 922 954 QPtrList<QSockNot> *list = d->sn_vec[type].list; 923 fd_set *fds = &d->sn_vec[type].enabled_fds;924 955 QSockNot *sn; 925 956 if ( ! list ) … … 931 962 return; 932 963 933 FD_CLR( sockfd, fds ); // clear fd bit 934 FD_CLR( sockfd, sn->queue ); 964 // touch fd bitmaps only if there are no other notifiers for the same socket 965 // (QPtrList curiously lacks getNext()/getPrev(), so play tambourine) 966 QSockNot *next = list->next(); 967 if ( next ) list->prev(); 968 else list->last(); 969 QSockNot *prev = list->prev(); 970 if ( prev ) list->next(); 971 else list->first(); 972 bool unique = (!next || next->fd != sockfd) && (!prev || prev->fd != sockfd); 973 if ( unique) { 974 FD_CLR( sockfd, sn->active ); // clear fd bit 975 FD_CLR( sockfd, sn->queue ); 976 } 935 977 d->sn_pending_list.removeRef( sn ); // remove from activation list 936 978 list->remove(); // remove notifier found above 937 979 938 if ( d->sn_highest == sockfd ) { // find highest fd 939 d->sn_highest = -1; 940 for ( int i=0; i<3; i++ ) { 941 if ( d->sn_vec[i].list && ! d->sn_vec[i].list->isEmpty() ) 942 d->sn_highest = QMAX( d->sn_highest, // list is fd-sorted 943 d->sn_vec[i].list->getFirst()->fd ); 944 } 980 if ( unique) { 981 if ( d->sn_highest == sockfd ) 982 find_highest_fd( d ); 945 983 } 946 984 #endif // QT_THREAD_SUPPORT … … 967 1005 968 1006 QMutexLocker locker( &ss_mutex ); 1007 ss_thread->cancelSelectOrIdle(); 969 1008 970 1009 QPtrList<QSockNot> *list = d->sn_vec[type].list; … … 990 1029 sn 991 1030 ); 992 FD_SET( sn->fd, sn->queue ); 1031 FD_SET( sockfd, sn->queue ); 1032 // remove from enabled sockets, see QSockSelectThread::run() 1033 FD_CLR( sockfd, sn->active ); 1034 if ( d->sn_highest == sockfd ) 1035 find_highest_fd( d ); 993 1036 } 994 1037 #endif // QT_THREAD_SUPPORT … … 1128 1171 1129 1172 // postpone activation if ss_thread is working with the list 1130 if ( !ss_mutex.tryLock() ) 1173 if ( !ss_mutex.tryLock() ) { 1174 qt_aux_win.post( WM_U_SEM_SELECT, 0, 0 ); 1131 1175 return 0; 1176 } 1177 1178 ss_thread->cancelSelectOrIdle(); 1132 1179 1133 1180 // activate entries … … 1141 1188 if ( FD_ISSET(sn->fd, sn->queue) ) { 1142 1189 FD_CLR( sn->fd, sn->queue ); 1190 // reenable the socket to let it participate in the next select() 1191 FD_SET( sn->fd, sn->active ); 1192 d->sn_highest = QMAX( d->sn_highest, sn->fd ); 1143 1193 QApplication::sendEvent( sn->obj, &event ); 1144 1194 n_act++;
Note:
See TracChangeset
for help on using the changeset viewer.