Changeset 176
- Timestamp:
- Feb 19, 2008, 12:35:23 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel/qeventloop_pm.cpp
r132 r176 63 63 static HMQ qt_gui_queue = 0; 64 64 65 #ifdef QT_PM_NO_DOSTIMERS 66 static bool dispatchTimer( uint, QMSG * ); 67 #endif 68 static void activateZeroTimers(); 69 65 70 static void initTimers(); 66 71 static void cleanupTimers(); 67 static bool dispatchTimer( uint, QMSG * );68 static bool activateTimer( uint );69 static void activateZeroTimers();70 72 71 73 static int numZeroTimers = 0; // number of full-speed timers … … 111 113 /*! 112 114 \class QPMObjectWindow qwindowdefs.h 113 115 114 116 The QPMObjectWindow class is an auxiliary class for dedicated message 115 117 processing. Its functionality is based on PM object windows. Once an instance … … 119 121 window handle of this object window is necessary to be passed as a HWND 120 122 argument to other calls and/or messages. 121 123 122 124 Instances of this class must be created on the main GUI thread only or on a 123 125 thread that has created a PM message queue and runs the PM message loop 124 126 \b itself. If you create an instance on a thread other than main, make sure 125 127 you destroy it before destroying the thread's message queue. 126 128 127 129 \note WM_CREATE and WM_DESTROY messages are processed internally and not 128 130 delivered do the message() method. Instead, you can use the constructor and 129 131 the destructor of the subclasses, respectively. 130 132 131 133 \note This class is non-portable! 132 134 */ … … 158 160 /*! 159 161 Destroys this object window. 160 This method calls destroy() to free the PM object window. 162 This method calls destroy() to free the PM object window. 161 163 */ 162 164 QPMObjectWindow::~QPMObjectWindow() … … 171 173 already created. The handle of the successfully created object window can 172 174 be obtained using the hwnd() method. 173 175 174 176 \note Must be called on the same thread that cosnstructed this instance. 175 177 */ … … 178 180 if ( w != NULLHANDLE ) 179 181 return FALSE; 180 182 181 183 static const char *ClassName = "QPMObjectWindow"; 182 184 static bool classRegistered = FALSE; 183 185 184 186 if ( !classRegistered ) { 185 187 WinRegisterClass( 0, ClassName, windowProc, 0, QWL_USER + sizeof(PVOID) ); … … 193 195 if ( w == NULLHANDLE ) 194 196 qSystemWarning( "QPMObjectWindow: Failed to create object window" ); 195 #endif 197 #endif 196 198 197 199 if ( w != NULLHANDLE && qt_gui_queue && … … 200 202 qt_objWindows.append( &w ); 201 203 } 202 204 203 205 return w != NULLHANDLE; 204 206 } … … 209 211 The method does nothing but returns \c FALSE if the window has been 210 212 already destroyed (or never created). 211 213 212 214 \note Must be called on the same thread that cosnstructed this instance. 213 215 */ … … 216 218 if ( w == NULLHANDLE ) 217 219 return FALSE; 218 220 219 221 if ( qt_gui_queue && qt_WinQueryQueue( 0 ) == qt_gui_queue ) { 220 222 // remove the handle from the 'clean destruction' list … … 225 227 w = 0; // tell windowProc() we're unsafe 226 228 WinDestroyWindow( h ); 227 229 228 230 return TRUE; 229 231 } … … 244 246 static_cast< QPMObjectWindow * >( WinQueryWindowPtr( hwnd, QWL_USER ) ); 245 247 Q_ASSERT( that ); 246 248 247 249 // Note: before WinCreateWindow() returns to the constructor or after the 248 250 // destructor has been called, w is 0. We use this to determine that the … … 251 253 if ( !that || !that->w ) 252 254 return (MRESULT) FALSE; 253 255 254 256 return that->message( msg, mp1, mp2 ); 255 257 } … … 257 259 /*! 258 260 \fn QPMObjectWindow::send( ULONG msg, MPARAM mp1, MPARAM mp2 ) const 259 261 260 262 Synchronously sends a message \a msg with the given parameters \a mp1 and 261 263 \a mp2 to this window handle and returns a reply from the message() function. 262 264 263 265 \note Must be called on the same thread that cosnstructed this instance. 264 266 */ … … 266 268 /*! 267 269 \fn QPMObjectWindow::post( ULONG msg, MPARAM mp1, MPARAM mp2 ) const 268 270 269 271 Asynchronously posts a message \a msg with the given parameters \a mp1 and 270 272 \a mp2 to this window handle. Returns \c TRUE on success and \c FALSE 271 273 otherwise. 272 274 273 275 \note Can be called on any thread. 274 276 */ … … 310 312 } 311 313 case WM_TIMER: { 314 #ifndef QT_PM_NO_DOSTIMERS 315 QApplication::sendPostedEvents( NULL, QEvent::Timer ); 316 break; 317 #else // ifndef QT_PM_NO_DOSTIMERS 312 318 USHORT id = SHORT1FROMMP( mp1 ); 313 319 QMSG qmsg = { hwnd(), msg, mp1, mp2 }; 314 320 dispatchTimer( (uint) id, &qmsg ); 315 321 break; 322 #endif // ifndef QT_PM_NO_DOSTIMERS 316 323 } 317 324 } 318 325 319 326 return FALSE; 320 327 } … … 382 389 need some extra handling to activate objects at timeout. 383 390 384 Implementation note: There are two types of timer identifiers. PM 385 timer ids (internal use) are stored in TimerInfo. Qt timer ids are 386 indexes (+1) into the timerVec vector. 391 There are two implemetations of Qt timers. When QT_PM_NO_DOSTIMERS is defined 392 (NOT by default), Qt uses PM timers. In this case, there are two types of 393 timer identifiers. PM timer ids (internal use) are stored in TimerInfo. Qt 394 timer ids are indexes (+1) into the timerVec vector. Note that this PM timer 395 based implementation is error-prone due to stupid PM limitations: there are 396 only several dozens of PM timers per the whole system and this number is 397 shared across all processes (e.g. if you create too many timers, other 398 applications that also need them will suck). 399 400 When QT_PM_NO_DOSTIMERS is not defined (by default), Qt uses its own timer 401 implementation based on a signle DosAsyncTimer() and a dedicated timer thread. 402 This implementation allows virtually unlimited number of Qt timers. In this 403 case, there is only one type of type identifiers: Qt timer identifiers are 404 indexes (+1) into the timeDict dictionary. 387 405 388 406 NOTE: These functions are for internal use. QObject::startTimer() and … … 418 436 // 419 437 420 #include "qptrvector.h" 421 #include "qintdict.h" 422 423 struct TimerInfo { // internal timer info 424 uint ind; // - Qt timer identifier - 1 425 ULONG id; // - PM timer identifier 426 bool zero; // - zero timing 427 QObject *obj; // - object to receive events 428 }; 429 typedef QPtrVector<TimerInfo> TimerVec; // vector of TimerInfo structs 430 typedef QIntDict<TimerInfo> TimerDict; // fast dict of timers 431 432 static TimerVec *timerVec = 0; // timer vector 433 static TimerDict *timerDict = 0; // timer dict 434 435 template <typename T> // template to track availability 436 class QFreeValueList // of free (unused) integer 437 { // values within some interval 438 // 439 // Template to track availability of free (unused) integer values within some 440 // interval. Note that take() and give() maintain spans sorted in ascending 441 // order. 442 // 443 template <typename T> 444 class QFreeValueList 445 { 438 446 public: 439 447 QFreeValueList( T min, T max ) : intMin( min ), intMax( max ) { … … 450 458 void give( T val ) { 451 459 Q_ASSERT( val >= intMin && val <= intMax ); 460 // look for the span to join 452 461 typename FreeList::iterator it = freeValues.begin(); 453 462 for ( ; it != freeValues.end(); ++ it ) { 454 463 Span &span = (*it); 455 464 if ( val == span.min - 1 ) { 465 // join the less end of span 456 466 span.min --; 457 467 typename FreeList::iterator it2 = it; … … 462 472 return; 463 473 } else if ( val == span.max + 1 ) { 474 // join the greater end of span 464 475 span.max ++; 465 476 typename FreeList::iterator it2 = it; … … 469 480 } 470 481 return; 482 } else if ( val < span.min ) { 483 // all the following spans are too "far" to join 484 break; 471 485 } 472 else if ( val < span.min ) 473 break; 486 // span must not include val (contradicts take()) 474 487 Q_ASSERT( val > span.max ); 475 488 } … … 493 506 }; 494 507 508 #ifndef QT_PM_NO_DOSTIMERS 509 510 #include "qintdict.h" 511 512 struct TimerInfo { // internal timer info 513 uint ind; // - Qt timer identifier - 1 (= index in vector) 514 ULONG interval; // - timeout interval, milliseconds 515 ULONG last; // - last shot timestamp 516 QObject *obj; // - object to receive events 517 }; 518 519 typedef QIntDict<TimerInfo> TimerDict; // dict of TimerInfo structs 520 static TimerDict *timerDict = NULL; 521 522 static QMutex timerMutex; // mutex protecting timerDict 523 524 typedef QFreeValueList<int> FreeQtTIDList; // list of free Qt timer IDs 525 static FreeQtTIDList *freeQtTIDs = NULL; 526 527 // 528 // Auxiliary timer thread to wait for Dos timer events and post Qt timer events. 529 // 530 static class QTimerThread : public QThread 531 { 532 public: 533 QTimerThread(); 534 virtual ~QTimerThread(); 535 void run(); 536 void signalQuit(); 537 void ensureShot( int ival ); 538 private: 539 HEV hev; // OS/2 timer event semaphore 540 HTIMER htimer; // OS/2 timer 541 ULONG interval; // OS/2 timer interval 542 bool quit : 1; // quit flag 543 } *timerThread = NULL; 544 545 QTimerThread::QTimerThread() 546 : hev( NULLHANDLE ), htimer( NULLHANDLE ) 547 , interval( 0 ), quit( false ) 548 { 549 APIRET rc; 550 rc = DosCreateEventSem( NULL, &hev, DC_SEM_SHARED, 0 /* reset */); 551 Q_ASSERT( rc == NO_ERROR ); 552 } 553 554 QTimerThread::~QTimerThread() 555 { 556 if ( hev != NULLHANDLE ) { 557 DosCloseEventSem( hev ); 558 hev = NULLHANDLE; 559 } 560 } 561 562 void QTimerThread::run() 563 { 564 APIRET rc; 565 ULONG now = 0; 566 567 do { 568 rc = DosWaitEventSem( hev, SEM_INDEFINITE_WAIT ); 569 Q_ASSERT( rc == NO_ERROR ); 570 if ( quit ) 571 break; 572 573 // get current time again and calculate the interval 574 DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &now, sizeof(now) ); 575 576 // go through all timers and see which were shot 577 578 QMutexLocker lock( &timerMutex ); 579 580 ULONG minLeft = ULONG_MAX; 581 582 QIntDictIterator<TimerInfo> it( *timerDict ); 583 for ( register TimerInfo *t; (t = it.current()); ++it ) { 584 ULONG spent = now - t->last; 585 if ( spent >= t->interval ) { 586 // the timer iterval has expired, post the timer event 587 QTimerEvent *e = new QTimerEvent( t->ind + 1 ); 588 QApplication::postEvent( t->obj, e ); 589 // set the new last stamp 590 t->last += t->interval * (spent / t->interval); 591 } 592 // calculate minimal time to the next shot 593 minLeft = QMIN( minLeft, t->interval - (spent % t->interval) ); 594 } 595 596 if ( timerDict->count() > 0 ) { 597 // post a spare WM_TIMER message to make sure timers run even when 598 // the message loop is not controlled by QEventLoop::processEvents() 599 // (e.g. when moving or resizing a window using the mouse) 600 WinPostMsg( qt_aux_win.hwnd(), WM_TIMER, 0, 0 ); 601 // restart the OS/2 timer 602 interval = minLeft; 603 ULONG postCnt; 604 DosResetEventSem( hev, &postCnt ); 605 // check for quit (cancelQuit() could post the semaphore just before 606 // we reset it above) 607 if ( quit ) 608 break; 609 rc = DosAsyncTimer( minLeft, (HSEM) hev, &htimer ); 610 Q_ASSERT( rc == NO_ERROR ); 611 } else { 612 htimer = NULLHANDLE; 613 interval = 0; 614 } 615 616 } while (1); 617 } 618 619 void QTimerThread::signalQuit() 620 { 621 quit = true; 622 DosPostEventSem( hev ); 623 wait(); 624 } 625 626 // Note: must be called from under timerMutex! 627 void QTimerThread::ensureShot( int ival ) 628 { 629 Q_ASSERT( timerMutex.locked() ); 630 Q_ASSERT( ival > 0 ); 631 if ( interval == 0 || interval > (ULONG) ival ) { 632 // start another timer to make sure the new Qt timer is fired off in time 633 interval = (ULONG) ival; 634 APIRET rc = DosAsyncTimer( interval, (HSEM) hev, &htimer ); 635 Q_ASSERT( rc == NO_ERROR ); 636 } 637 } 638 639 #else // ifndef QT_PM_NO_DOSTIMERS 640 641 #include "qptrvector.h" 642 #include "qintdict.h" 643 644 struct TimerInfo { // internal timer info 645 uint ind; // - Qt timer identifier - 1 646 ULONG id; // - PM timer identifier 647 bool zero; // - zero timing 648 QObject *obj; // - object to receive events 649 }; 650 typedef QPtrVector<TimerInfo> TimerVec; // vector of TimerInfo structs 651 typedef QIntDict<TimerInfo> TimerDict; // fast dict of timers 652 653 static TimerVec *timerVec = 0; // timer vector 654 static TimerDict *timerDict = 0; // timer dict 655 495 656 typedef QFreeValueList<int> FreeQtTIDList; // list of free Qt timer IDs 496 657 static FreeQtTIDList *freeQtTIDs = 0; … … 498 659 static FreePMTIDList *freePMTIDs = 0; 499 660 500 // Activate a timer, used by both event-loop based and simple timers.501 502 static bool dispatchTimer( uint timerId, QMSG *msg )503 {504 MRESULT res = NULL;505 if ( !msg || !qApp || !qt_pmEventFilter(msg,res) )506 return activateTimer( timerId );507 return TRUE;508 }509 510 511 661 // 512 662 // Timer activation (called from the event loop when WM_TIMER arrives) 513 663 // 514 515 static bool activateTimer( uint id ) // activate timer 516 { 517 if ( !timerVec ) // should never happen 518 return FALSE; 519 register TimerInfo *t = timerDict->find( id ); 520 if ( !t ) // no such timer id 521 return FALSE; 522 QTimerEvent e( t->ind + 1 ); 523 QApplication::sendEvent( t->obj, &e ); // send event 524 return TRUE; // timer event was processed 525 } 526 527 static void activateZeroTimers() // activate full-speed timers 528 { 664 static bool dispatchTimer( uint timerId, QMSG *msg ) 665 { 666 MRESULT res = NULL; 667 if ( !msg || !qApp || !qt_pmEventFilter(msg,res) ) 668 { 669 if ( !timerVec ) // should never happen 670 return FALSE; 671 register TimerInfo *t = timerDict->find( timerId ); 672 if ( !t ) // no such timer id 673 return FALSE; 674 QTimerEvent e( t->ind + 1 ); 675 QApplication::sendEvent( t->obj, &e ); // send event 676 return TRUE; // timer event was processed 677 } 678 return TRUE; 679 } 680 681 #endif // ifndef QT_PM_NO_DOSTIMERS 682 683 // 684 // activate full-speed timers 685 // 686 static void activateZeroTimers() 687 { 688 #ifndef QT_PM_NO_DOSTIMERS 689 if ( !timerDict ) 690 return; 691 QIntDictIterator<TimerInfo> it( *timerDict ); 692 register TimerInfo *t = 0; 693 int n = numZeroTimers; 694 while ( n-- ) { 695 for ( ;; ) { 696 t = it(); 697 Q_ASSERT( t ); 698 if ( !t ) 699 return; 700 if ( t->interval == 0 ) 701 break; 702 } 703 QTimerEvent e( t->ind + 1 ); 704 QApplication::sendEvent( t->obj, &e ); 705 } 706 #else 529 707 if ( !timerVec ) 530 708 return; 531 709 uint i=0; 532 710 register TimerInfo *t = 0; 533 711 int n = numZeroTimers; 534 712 while ( n-- ) { 535 for ( ;; ) { 536 t = timerVec->at(i++); 537 if ( t && t->zero ) 538 break; 539 else if ( i == timerVec->size() ) // should not happen 540 return; 541 } 542 QTimerEvent e( t->ind + 1 ); 543 QApplication::sendEvent( t->obj, &e ); 544 } 713 for ( ;; ) { 714 t = timerVec->at(i++); 715 if ( t && t->zero ) 716 break; 717 else if ( i == timerVec->size() ) // should not happen 718 return; 719 } 720 QTimerEvent e( t->ind + 1 ); 721 QApplication::sendEvent( t->obj, &e ); 722 } 723 #endif 545 724 } 546 725 … … 552 731 static void initTimers() // initialize timers 553 732 { 733 #ifndef QT_PM_NO_DOSTIMERS 734 timerDict = new TimerDict( 29 ); 735 Q_CHECK_PTR( timerDict ); 736 timerDict->setAutoDelete( TRUE ); 737 freeQtTIDs = new FreeQtTIDList( 0, 1023 ); // resonable max amount of timers 738 Q_CHECK_PTR( freeQtTIDs ); 739 timerThread = new QTimerThread(); 740 Q_CHECK_PTR( timerThread ); 741 timerThread->start(); 742 #else // ifndef QT_PM_NO_DOSTIMERS 554 743 timerVec = new TimerVec( 128 ); 555 744 Q_CHECK_PTR( timerVec ); … … 557 746 timerDict = new TimerDict( 29 ); 558 747 Q_CHECK_PTR( timerDict ); 559 freeQtTIDs = new FreeQtTIDList( 0, INT_MAX );748 freeQtTIDs = new FreeQtTIDList( 0, 1023 ); // resonable max amount of timers 560 749 Q_CHECK_PTR( freeQtTIDs ); 561 750 freePMTIDs = new FreePMTIDList( 1, TID_USERMAX - 1 ); 562 751 Q_CHECK_PTR( freePMTIDs ); 752 #endif // ifndef QT_PM_NO_DOSTIMERS 563 753 } 564 754 … … 573 763 static void cleanupTimers() // remove pending timers 574 764 { 765 #ifndef QT_PM_NO_DOSTIMERS 766 if ( !timerDict ) // no timers were used 767 return; 768 timerThread->signalQuit(); 769 delete timerThread; 770 timerThread = NULL; 771 delete freeQtTIDs; 772 freeQtTIDs = NULL; 773 delete timerDict; 774 timerDict = NULL; 775 #else // ifndef QT_PM_NO_DOSTIMERS 575 776 register TimerInfo *t; 576 777 if ( !timerVec ) // no timers were used … … 589 790 delete timerVec; 590 791 timerVec = 0; 792 #endif // ifndef QT_PM_NO_DOSTIMERS 591 793 } 592 794 … … 600 802 { 601 803 Q_ASSERT( obj ); 602 if ( !obj )804 if ( !obj || interval < 0 ) 603 805 return 0; 604 605 // lazily create the auxiliary window to process WM_TIMER messages 806 807 // lazily create the auxiliary window to process WM_TIMER and 808 // WM_U_SEM_ZEROTIMER messages 606 809 if ( !qt_aux_win.hwnd() ) 607 810 if ( !qt_aux_win.create() ) 608 811 return 0; 609 610 register TimerInfo *t; 812 813 #ifndef QT_PM_NO_DOSTIMERS 814 if ( !timerDict ) // initialize timer data 815 initTimers(); 816 #else // ifndef QT_PM_NO_DOSTIMERS 611 817 if ( !timerVec ) // initialize timer data 612 initTimers(); 818 initTimers(); 819 #endif // ifndef QT_PM_NO_DOSTIMERS 613 820 614 821 if ( freeQtTIDs->isEmpty() ) { … … 619 826 return 0; 620 827 } 621 828 829 #ifdef QT_PM_NO_DOSTIMERS 622 830 if ( freePMTIDs->isEmpty() ) { 623 831 #if defined(QT_CHECK_STATE) … … 627 835 return 0; 628 836 } 629 630 int ind = freeQtTIDs->take(); // get free timer 837 #endif 838 839 int ind = freeQtTIDs->take(); // get free timer 840 841 #ifndef QT_PM_NO_DOSTIMERS 842 register TimerInfo *t = new TimerInfo; // create timer entry 843 Q_CHECK_PTR( t ); 844 t->ind = ind; 845 t->obj = obj; 846 847 t->interval = interval; 848 if ( t->interval == 0 ) { // add zero timer 849 numZeroTimers++; 850 // indicate there is a new zero timer 851 WinPostMsg( qt_aux_win.hwnd(), WM_U_SEM_ZEROTIMER, 0, 0 ); 852 } else { 853 // set the initial last shot timestamp value to now 854 DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &t->last, sizeof(t->last) ); 855 } 856 857 QMutexLocker lock( &timerMutex ); 858 timerDict->insert( ind, t ); // store in timer dict 859 if ( t->interval != 0 ) 860 timerThread->ensureShot( t->interval ); 861 #else // ifndef QT_PM_NO_DOSTIMERS 631 862 if ( (uint) ind >= timerVec->size() ) { 632 863 uint newSize = timerVec->size() * 4; // increase the size 633 864 if ( newSize <= (uint) ind ) 634 865 newSize = (uint) ind + 1; 635 timerVec->resize( newSize ); 636 } 637 t = new TimerInfo; // create timer entry 866 timerVec->resize( newSize ); 867 } 868 869 register TimerInfo *t = new TimerInfo; // create timer entry 638 870 Q_CHECK_PTR( t ); 639 871 t->ind = ind; … … 659 891 } 660 892 } 661 timerVec->insert( ind, t ); 893 timerVec->insert( ind, t ); // store in timer vector 662 894 if ( !t->zero ) 663 timerDict->insert( t->id, t ); // store in dict 664 return ind + 1; // return index in vector 895 timerDict->insert( t->id, t ); // store in dict 896 #endif // ifndef QT_PM_NO_DOSTIMERS 897 898 return ind + 1; // return index in vector 665 899 } 666 900 667 901 bool qKillTimer( int ind ) 668 902 { 903 #ifndef QT_PM_NO_DOSTIMERS 904 if ( !timerDict ) 905 return FALSE; 906 register TimerInfo *t = timerDict->find( ind-1 ); 907 if ( !t ) 908 return FALSE; 909 if ( t->interval == 0 ) { 910 numZeroTimers--; 911 } 912 freeQtTIDs->give( t->ind ); 913 QMutexLocker lock( &timerMutex ); 914 timerDict->remove( ind-1 ); 915 return TRUE; 916 #else // ifndef QT_PM_NO_DOSTIMERS 669 917 if ( !timerVec || ind <= 0 || (uint)ind > timerVec->size() ) 670 918 return FALSE; 671 919 register TimerInfo *t = timerVec->at(ind-1); 672 920 if ( !t ) 673 921 return FALSE; 674 922 if ( t->zero ) { 675 923 numZeroTimers--; 676 924 } else { 677 925 WinStopTimer( 0, qt_aux_win.hwnd(), t->id ); 678 926 freePMTIDs->give( t->id ); 679 927 timerDict->remove( t->id ); … … 682 930 timerVec->remove( ind-1 ); 683 931 return TRUE; 932 #endif // ifndef QT_PM_NO_DOSTIMERS 684 933 } 685 934 686 935 bool qKillTimer( QObject *obj ) 687 936 { 937 #ifndef QT_PM_NO_DOSTIMERS 938 if ( !timerDict ) 939 return FALSE; 940 QIntDictIterator<TimerInfo> it ( *timerDict ); 941 for ( register TimerInfo *t; (t = it.current()); ) { 942 if ( t->obj == obj ) { // object found 943 if ( t->interval == 0 ) { 944 numZeroTimers--; 945 } 946 freeQtTIDs->give( t->ind ); 947 QMutexLocker lock( &timerMutex ); 948 timerDict->remove( it.currentKey() ); 949 } else { 950 ++it; 951 } 952 } 953 return TRUE; 954 #else // ifndef QT_PM_NO_DOSTIMERS 688 955 if ( !timerVec ) 689 956 return FALSE; 690 957 register TimerInfo *t; 691 958 for ( uint i=0; i<timerVec->size(); i++ ) { 692 693 694 695 696 697 959 t = timerVec->at( i ); 960 if ( t && t->obj == obj ) { // object found 961 if ( t->zero ) { 962 numZeroTimers--; 963 } else { 964 WinStopTimer( 0, qt_aux_win.hwnd(), t->id ); 698 965 freePMTIDs->give( t->id ); 699 966 timerDict->remove( t->id ); 700 967 } 701 968 freeQtTIDs->give( t->ind ); 702 703 969 timerVec->remove( i ); 970 } 704 971 } 705 972 return TRUE; 973 #endif // ifndef QT_PM_NO_DOSTIMERS 706 974 } 707 975 … … 895 1163 qt_gui_queue = d->hmq; 896 1164 897 qt_aux_win.setEventLoop( this ); 1165 qt_aux_win.setEventLoop( this ); 898 1166 899 1167 #if defined(QT_THREAD_SUPPORT) … … 910 1178 void QEventLoop::cleanup() 911 1179 { 912 cleanupTimers(); 913 914 // ss_thread should have been stopped already in appClosingDown() 1180 // timers should have been already uninitialized in appClosingDown() 1181 #ifndef QT_PM_NO_DOSTIMERS 1182 Q_ASSERT( timerDict == 0 ); 1183 #else 1184 Q_ASSERT( timerVec == 0 ); 1185 #endif 1186 1187 // ss_thread should have been already stopped in appClosingDown() 915 1188 Q_ASSERT( ss_thread == 0 ); 916 917 qt_aux_win.setEventLoop( 0 ); 918 1189 1190 qt_aux_win.setEventLoop( 0 ); 1191 919 1192 // destroy all windows created by QPMObjectWindow instances 920 1193 for ( HWND *w = qt_objWindows.first(); w; w = qt_objWindows.next() ) { … … 922 1195 WinDestroyWindow( *w ); 923 1196 // tell QPMObjectWindow the window has been destroyed 924 *w = 0; 925 } 926 1197 *w = 0; 1198 } 1199 927 1200 WinDestroyMsgQueue( d->hmq ); 928 1201 WinTerminate( d->hab ); … … 937 1210 void QEventLoop::appClosingDown() 938 1211 { 939 // ensure the thread is terminated before QApplication calls1212 // ensure the socket thread is terminated before QApplication calls 940 1213 // QThread::cleanup() 941 1214 if ( ss_thread ) 942 1215 ss_cleanup(); 1216 // the same applies to the timer thread 1217 cleanupTimers(); 943 1218 } 944 1219 … … 975 1250 QMutexLocker locker( &ss_mutex ); 976 1251 ss_thread->cancelSelectOrIdle(); 977 1252 978 1253 QPtrList<QSockNot> *list = d->sn_vec[type].list; 979 1254 QSockNot *sn; … … 1039 1314 if ( !ss_thread ) 1040 1315 return; // definitely not found 1041 1316 1042 1317 QMutexLocker locker( &ss_mutex ); 1043 1318 ss_thread->cancelSelectOrIdle(); … … 1094 1369 if ( !ss_thread ) 1095 1370 return; // definitely not found 1096 1371 1097 1372 QMutexLocker locker( &ss_mutex ); 1098 1373 ss_thread->cancelSelectOrIdle(); … … 1145 1420 QApplication::sendPostedEvents(); 1146 1421 1422 #ifndef QT_PM_NO_DOSTIMERS 1423 // we've just processed all pending events above, including QEvent::Timer 1424 // events, so remove spare WM_TIMER messages posted to qt_aux_win for the 1425 // cases when the message loop is run bypassing this method 1426 if ( qt_aux_win.hwnd() ) 1427 WinPeekMsg( 0, &msg, qt_aux_win.hwnd(), WM_TIMER, WM_TIMER, PM_REMOVE ); 1428 #endif // ifndef QT_PM_NO_DOSTIMERS 1429 1147 1430 if ( flags & ExcludeUserInput ) { 1148 1431 while ( WinPeekMsg( 0, &msg, 0, 0, 0, PM_NOREMOVE ) ) { … … 1163 1446 1164 1447 bool canWait = d->exitloop || d->quitnow ? FALSE : (flags & WaitForMore); 1165 1448 1166 1449 if ( canWait ) { 1167 1450 // can wait if necessary … … 1184 1467 } 1185 1468 } 1186 1469 1187 1470 if ( msg.msg == WM_QUIT ) { 1188 1471 // process the quit request 1189 1472 #if !defined (QT_NO_SESSIONMANAGER) 1190 1473 if ( qt_app_canQuit() ) { 1191 #endif 1474 #endif 1192 1475 exit( 0 ); 1193 1476 return TRUE; … … 1197 1480 return TRUE; 1198 1481 } 1199 #endif 1482 #endif 1200 1483 } 1201 1484 … … 1211 1494 flags |= ExcludeSocketNotifiers; 1212 1495 } 1213 1496 1214 1497 if ( !handled && msg.msg && (!msg.hwnd || !QWidget::find( msg.hwnd )) ) { 1215 1498 handled = qt_pmEventFilter( &msg, res ); … … 1224 1507 activateSocketNotifiers(); 1225 1508 1226 // any pending configs? 1509 // any pending configs? 1227 1510 if ( configRequests ) 1228 1511 qPMProcessConfigRequests(); … … 1260 1543 if ( !ss_thread ) 1261 1544 return 0; 1262 1545 1263 1546 // postpone activation if ss_thread is working with the list 1264 1547 if ( !ss_mutex.tryLock() ) { … … 1279 1562 if ( FD_ISSET(sn->fd, sn->queue) ) { 1280 1563 FD_CLR( sn->fd, sn->queue ); 1281 // reenable the socket to let it participate in the next select() 1564 // reenable the socket to let it participate in the next select() 1282 1565 FD_SET( sn->fd, sn->active ); 1283 1566 d->sn_highest = QMAX( d->sn_highest, sn->fd );
Note:
See TracChangeset
for help on using the changeset viewer.