tests/auto/qwaitcondition/tst_qwaitcondition.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 
       
    43 #include <QtTest/QtTest>
       
    44 
       
    45 #include <qcoreapplication.h>
       
    46 #include <qmutex.h>
       
    47 #include <qthread.h>
       
    48 #include <qwaitcondition.h>
       
    49 
       
    50 #if defined(Q_OS_SYMBIAN)
       
    51 // Symbian Open C has a bug that causes very short waits to fail sometimes
       
    52 #define COND_WAIT_TIME 50
       
    53 #else
       
    54 #define COND_WAIT_TIME 1
       
    55 #endif
       
    56 
       
    57 
       
    58 //TESTED_CLASS=
       
    59 //TESTED_FILES=
       
    60 
       
    61 class tst_QWaitCondition : public QObject
       
    62 {
       
    63     Q_OBJECT
       
    64 
       
    65 public:
       
    66     tst_QWaitCondition();
       
    67 
       
    68 private slots:
       
    69     void wait_QMutex();
       
    70     void wait_QReadWriteLock();
       
    71     void wakeOne();
       
    72     void wakeAll();
       
    73     void wait_RaceCondition();
       
    74 };
       
    75 
       
    76 static const int iterations = 10;
       
    77 
       
    78 // Note: some tests rely on ThreadCount being multiple of 2
       
    79 #ifdef Q_OS_SOLARIS
       
    80 static const int ThreadCount = 4;
       
    81 #else
       
    82 static const int ThreadCount = 10;
       
    83 #endif
       
    84 
       
    85 tst_QWaitCondition::tst_QWaitCondition()
       
    86 
       
    87 {
       
    88 }
       
    89 
       
    90 class wait_QMutex_Thread_1 : public QThread
       
    91 {
       
    92 public:
       
    93     QMutex mutex;
       
    94     QWaitCondition cond;
       
    95 
       
    96     inline wait_QMutex_Thread_1()
       
    97     { }
       
    98 
       
    99     void run()
       
   100     {
       
   101     mutex.lock();
       
   102     cond.wakeOne();
       
   103     cond.wait(&mutex);
       
   104     mutex.unlock();
       
   105     }
       
   106 };
       
   107 
       
   108 class wait_QMutex_Thread_2 : public QThread
       
   109 {
       
   110 public:
       
   111     QWaitCondition started;
       
   112 
       
   113     QMutex *mutex;
       
   114     QWaitCondition *cond;
       
   115 
       
   116     inline wait_QMutex_Thread_2()
       
   117     : mutex(0), cond(0)
       
   118     { }
       
   119 
       
   120     void run()
       
   121     {
       
   122     mutex->lock();
       
   123     started.wakeOne();
       
   124     cond->wait(mutex);
       
   125     mutex->unlock();
       
   126     }
       
   127 };
       
   128 
       
   129 class wait_QReadWriteLock_Thread_1 : public QThread
       
   130 {
       
   131 public:
       
   132     QReadWriteLock readWriteLock;
       
   133     QWaitCondition cond;
       
   134 
       
   135     inline wait_QReadWriteLock_Thread_1()
       
   136     { }
       
   137 
       
   138     void run()
       
   139     {
       
   140     readWriteLock.lockForWrite();
       
   141     cond.wakeOne();
       
   142     cond.wait(&readWriteLock);
       
   143     readWriteLock.unlock();
       
   144     }
       
   145 };
       
   146 
       
   147 class wait_QReadWriteLock_Thread_2 : public QThread
       
   148 {
       
   149 public:
       
   150     QWaitCondition started;
       
   151 
       
   152     QReadWriteLock *readWriteLock;
       
   153     QWaitCondition *cond;
       
   154 
       
   155     inline wait_QReadWriteLock_Thread_2()
       
   156     : readWriteLock(0), cond(0)
       
   157     { }
       
   158 
       
   159     void run()
       
   160     {
       
   161     readWriteLock->lockForRead();
       
   162     started.wakeOne();
       
   163     cond->wait(readWriteLock);
       
   164     readWriteLock->unlock();
       
   165     }
       
   166 };
       
   167 
       
   168 void tst_QWaitCondition::wait_QMutex()
       
   169 {
       
   170     int x;
       
   171     for (int i = 0; i < iterations; ++i) {
       
   172     {
       
   173         QMutex mutex;
       
   174         QWaitCondition cond;
       
   175 
       
   176         mutex.lock();
       
   177 
       
   178         cond.wakeOne();
       
   179         QVERIFY(!cond.wait(&mutex, 1));
       
   180 
       
   181         cond.wakeAll();
       
   182         QVERIFY(!cond.wait(&mutex, 1));
       
   183 
       
   184         mutex.unlock();
       
   185     }
       
   186 
       
   187     {
       
   188         // test multiple threads waiting on separate wait conditions
       
   189         wait_QMutex_Thread_1 thread[ThreadCount];
       
   190 
       
   191         for (x = 0; x < ThreadCount; ++x) {
       
   192         thread[x].mutex.lock();
       
   193         thread[x].start();
       
   194         // wait for thread to start
       
   195         QVERIFY(thread[x].cond.wait(&thread[x].mutex, 1000));
       
   196         thread[x].mutex.unlock();
       
   197         }
       
   198 
       
   199         for (x = 0; x < ThreadCount; ++x) {
       
   200         QVERIFY(thread[x].isRunning());
       
   201         QVERIFY(!thread[x].isFinished());
       
   202         }
       
   203 
       
   204         for (x = 0; x < ThreadCount; ++x) {
       
   205         thread[x].mutex.lock();
       
   206         thread[x].cond.wakeOne();
       
   207         thread[x].mutex.unlock();
       
   208         }
       
   209 
       
   210         for (x = 0; x < ThreadCount; ++x) {
       
   211         QVERIFY(thread[x].wait(1000));
       
   212         }
       
   213     }
       
   214 
       
   215     {
       
   216         // test multiple threads waiting on a wait condition
       
   217         QMutex mutex;
       
   218         QWaitCondition cond1, cond2;
       
   219         wait_QMutex_Thread_2 thread[ThreadCount];
       
   220 
       
   221         mutex.lock();
       
   222         for (x = 0; x < ThreadCount; ++x) {
       
   223         thread[x].mutex = &mutex;
       
   224         thread[x].cond = (x < ThreadCount / 2) ? &cond1 : &cond2;
       
   225         thread[x].start();
       
   226         // wait for thread to start
       
   227         QVERIFY(thread[x].started.wait(&mutex, 1000));
       
   228         }
       
   229         mutex.unlock();
       
   230 
       
   231         for (x = 0; x < ThreadCount; ++x) {
       
   232         QVERIFY(thread[x].isRunning());
       
   233         QVERIFY(!thread[x].isFinished());
       
   234         }
       
   235 
       
   236         mutex.lock();
       
   237         cond1.wakeAll();
       
   238         cond2.wakeAll();
       
   239         mutex.unlock();
       
   240 
       
   241         for (x = 0; x < ThreadCount; ++x) {
       
   242         QVERIFY(thread[x].wait(1000));
       
   243         }
       
   244     }
       
   245     }
       
   246 }
       
   247 
       
   248 void tst_QWaitCondition::wait_QReadWriteLock()
       
   249 {
       
   250     {
       
   251         QReadWriteLock readWriteLock(QReadWriteLock::Recursive);
       
   252         QWaitCondition waitCondition;
       
   253 
       
   254         // ensure that the lockForRead is correctly restored
       
   255         readWriteLock.lockForRead();
       
   256 
       
   257         QVERIFY(!waitCondition.wait(&readWriteLock, 1));
       
   258 
       
   259         QVERIFY(!readWriteLock.tryLockForWrite());
       
   260         QVERIFY(readWriteLock.tryLockForRead());
       
   261         readWriteLock.unlock();
       
   262         QVERIFY(!readWriteLock.tryLockForWrite());
       
   263         readWriteLock.unlock();
       
   264 
       
   265         QVERIFY(readWriteLock.tryLockForWrite());
       
   266         readWriteLock.unlock();
       
   267     }
       
   268 
       
   269     {
       
   270         QReadWriteLock readWriteLock(QReadWriteLock::Recursive);
       
   271         QWaitCondition waitCondition;
       
   272 
       
   273         // ensure that the lockForWrite is correctly restored
       
   274         readWriteLock.lockForWrite();
       
   275 
       
   276         QVERIFY(!waitCondition.wait(&readWriteLock, 1));
       
   277 
       
   278         QVERIFY(!readWriteLock.tryLockForRead());
       
   279         QVERIFY(readWriteLock.tryLockForWrite());
       
   280         readWriteLock.unlock();
       
   281         QVERIFY(!readWriteLock.tryLockForRead());
       
   282         readWriteLock.unlock();
       
   283 
       
   284         QVERIFY(readWriteLock.tryLockForRead());
       
   285         readWriteLock.unlock();
       
   286     }
       
   287 
       
   288 
       
   289     int x;
       
   290     for (int i = 0; i < iterations; ++i) {
       
   291     {
       
   292         QReadWriteLock readWriteLock;
       
   293         QWaitCondition waitCondition;
       
   294 
       
   295         readWriteLock.lockForRead();
       
   296 
       
   297         waitCondition.wakeOne();
       
   298         QVERIFY(!waitCondition.wait(&readWriteLock, 1));
       
   299 
       
   300         waitCondition.wakeAll();
       
   301         QVERIFY(!waitCondition.wait(&readWriteLock, 1));
       
   302 
       
   303         readWriteLock.unlock();
       
   304     }
       
   305 
       
   306     {
       
   307         QReadWriteLock readWriteLock;
       
   308         QWaitCondition waitCondition;
       
   309 
       
   310         readWriteLock.lockForWrite();
       
   311 
       
   312         waitCondition.wakeOne();
       
   313         QVERIFY(!waitCondition.wait(&readWriteLock, 1));
       
   314 
       
   315         waitCondition.wakeAll();
       
   316         QVERIFY(!waitCondition.wait(&readWriteLock, 1));
       
   317 
       
   318         readWriteLock.unlock();
       
   319     }
       
   320 
       
   321     {
       
   322         // test multiple threads waiting on separate wait conditions
       
   323         wait_QReadWriteLock_Thread_1 thread[ThreadCount];
       
   324 
       
   325         for (x = 0; x < ThreadCount; ++x) {
       
   326         thread[x].readWriteLock.lockForRead();
       
   327         thread[x].start();
       
   328         // wait for thread to start
       
   329 #if defined(Q_OS_SYMBIAN) && defined(Q_CC_WINSCW)
       
   330         // Symbian emulator startup simultaneously with this thread causes additional delay
       
   331         QVERIFY(thread[x].cond.wait(&thread[x].readWriteLock, 10000));
       
   332 #else
       
   333         QVERIFY(thread[x].cond.wait(&thread[x].readWriteLock, 1000));
       
   334 #endif
       
   335         thread[x].readWriteLock.unlock();
       
   336         }
       
   337 
       
   338         for (x = 0; x < ThreadCount; ++x) {
       
   339         QVERIFY(thread[x].isRunning());
       
   340         QVERIFY(!thread[x].isFinished());
       
   341         }
       
   342 
       
   343         for (x = 0; x < ThreadCount; ++x) {
       
   344         thread[x].readWriteLock.lockForRead();
       
   345         thread[x].cond.wakeOne();
       
   346         thread[x].readWriteLock.unlock();
       
   347         }
       
   348 
       
   349         for (x = 0; x < ThreadCount; ++x) {
       
   350         QVERIFY(thread[x].wait(1000));
       
   351         }
       
   352     }
       
   353 
       
   354     {
       
   355         // test multiple threads waiting on a wait condition
       
   356         QReadWriteLock readWriteLock;
       
   357         QWaitCondition cond1, cond2;
       
   358         wait_QReadWriteLock_Thread_2 thread[ThreadCount];
       
   359 
       
   360         readWriteLock.lockForWrite();
       
   361         for (x = 0; x < ThreadCount; ++x) {
       
   362         thread[x].readWriteLock = &readWriteLock;
       
   363         thread[x].cond = (x < ThreadCount / 2) ? &cond1 : &cond2;
       
   364         thread[x].start();
       
   365         // wait for thread to start
       
   366         QVERIFY(thread[x].started.wait(&readWriteLock, 1000));
       
   367         }
       
   368         readWriteLock.unlock();
       
   369 
       
   370         for (x = 0; x < ThreadCount; ++x) {
       
   371         QVERIFY(thread[x].isRunning());
       
   372         QVERIFY(!thread[x].isFinished());
       
   373         }
       
   374 
       
   375         readWriteLock.lockForWrite();
       
   376         cond1.wakeAll();
       
   377         cond2.wakeAll();
       
   378         readWriteLock.unlock();
       
   379 
       
   380         for (x = 0; x < ThreadCount; ++x) {
       
   381         QVERIFY(thread[x].wait(1000));
       
   382         }
       
   383     }
       
   384     }
       
   385 
       
   386 }
       
   387 
       
   388 class wake_Thread : public QThread
       
   389 {
       
   390 public:
       
   391     static int count;
       
   392 
       
   393     QWaitCondition started;
       
   394     QWaitCondition dummy;
       
   395 
       
   396     QMutex *mutex;
       
   397     QWaitCondition *cond;
       
   398 
       
   399     inline wake_Thread()
       
   400     : mutex(0), cond(0)
       
   401     { }
       
   402 
       
   403     static inline void sleep(ulong s)
       
   404     { QThread::sleep(s); }
       
   405 
       
   406     void run()
       
   407     {
       
   408     mutex->lock();
       
   409     ++count;
       
   410         dummy.wakeOne(); // this wakeup should be lost
       
   411            started.wakeOne();
       
   412         dummy.wakeAll(); // this one too
       
   413     cond->wait(mutex);
       
   414         --count;
       
   415     mutex->unlock();
       
   416     }
       
   417 };
       
   418 
       
   419 int wake_Thread::count = 0;
       
   420 
       
   421 class wake_Thread_2 : public QThread
       
   422 {
       
   423 public:
       
   424     static int count;
       
   425 
       
   426     QWaitCondition started;
       
   427     QWaitCondition dummy;
       
   428 
       
   429     QReadWriteLock *readWriteLock;
       
   430     QWaitCondition *cond;
       
   431 
       
   432     inline wake_Thread_2()
       
   433     : readWriteLock(0), cond(0)
       
   434     { }
       
   435 
       
   436     static inline void sleep(ulong s)
       
   437     { QThread::sleep(s); }
       
   438 
       
   439     void run()
       
   440     {
       
   441     readWriteLock->lockForWrite();
       
   442     ++count;
       
   443         dummy.wakeOne(); // this wakeup should be lost
       
   444         started.wakeOne();
       
   445         dummy.wakeAll(); // this one too
       
   446     cond->wait(readWriteLock);
       
   447         --count;
       
   448     readWriteLock->unlock();
       
   449     }
       
   450 };
       
   451 
       
   452 int wake_Thread_2::count = 0;
       
   453 
       
   454 void tst_QWaitCondition::wakeOne()
       
   455 {
       
   456     int x;
       
   457     // wake up threads, one at a time
       
   458     for (int i = 0; i < iterations; ++i) {
       
   459     QMutex mutex;
       
   460     QWaitCondition cond;
       
   461 
       
   462     // QMutex
       
   463     wake_Thread thread[ThreadCount];
       
   464     bool thread_exited[ThreadCount];
       
   465 
       
   466     mutex.lock();
       
   467     for (x = 0; x < ThreadCount; ++x) {
       
   468         thread[x].mutex = &mutex;
       
   469         thread[x].cond = &cond;
       
   470         thread_exited[x] = FALSE;
       
   471         thread[x].start();
       
   472         // wait for thread to start
       
   473         QVERIFY(thread[x].started.wait(&mutex, 1000));
       
   474         // make sure wakeups are not queued... if nothing is
       
   475         // waiting at the time of the wakeup, nothing happens
       
   476         QVERIFY(!thread[x].dummy.wait(&mutex, 1));
       
   477     }
       
   478     mutex.unlock();
       
   479 
       
   480     QCOMPARE(wake_Thread::count, ThreadCount);
       
   481 
       
   482     // wake up threads one at a time
       
   483     for (x = 0; x < ThreadCount; ++x) {
       
   484         mutex.lock();
       
   485         cond.wakeOne();
       
   486         QVERIFY(!cond.wait(&mutex, COND_WAIT_TIME));
       
   487         QVERIFY(!thread[x].dummy.wait(&mutex, 1));
       
   488         mutex.unlock();
       
   489 
       
   490         int exited = 0;
       
   491         for (int y = 0; y < ThreadCount; ++y) {
       
   492             if (thread_exited[y])
       
   493                         continue;
       
   494             if (thread[y].wait(exited > 0 ? 3 : 1000)) {
       
   495                 thread_exited[y] = TRUE;
       
   496                 ++exited;
       
   497             }
       
   498         }
       
   499 
       
   500         QCOMPARE(exited, 1);
       
   501         QCOMPARE(wake_Thread::count, ThreadCount - (x + 1));
       
   502     }
       
   503 
       
   504     QCOMPARE(wake_Thread::count, 0);
       
   505 
       
   506     // QReadWriteLock
       
   507     QReadWriteLock readWriteLock;
       
   508     wake_Thread_2 rwthread[ThreadCount];
       
   509 
       
   510     readWriteLock.lockForWrite();
       
   511     for (x = 0; x < ThreadCount; ++x) {
       
   512         rwthread[x].readWriteLock = &readWriteLock;
       
   513         rwthread[x].cond = &cond;
       
   514         thread_exited[x] = FALSE;
       
   515         rwthread[x].start();
       
   516         // wait for thread to start
       
   517         QVERIFY(rwthread[x].started.wait(&readWriteLock, 1000));
       
   518         // make sure wakeups are not queued... if nothing is
       
   519         // waiting at the time of the wakeup, nothing happens
       
   520         QVERIFY(!rwthread[x].dummy.wait(&readWriteLock, 1));
       
   521     }
       
   522     readWriteLock.unlock();
       
   523 
       
   524     QCOMPARE(wake_Thread_2::count, ThreadCount);
       
   525 
       
   526     // wake up threads one at a time
       
   527     for (x = 0; x < ThreadCount; ++x) {
       
   528         readWriteLock.lockForWrite();
       
   529         cond.wakeOne();
       
   530         QVERIFY(!cond.wait(&readWriteLock, COND_WAIT_TIME));
       
   531         QVERIFY(!rwthread[x].dummy.wait(&readWriteLock, 1));
       
   532         readWriteLock.unlock();
       
   533 
       
   534         int exited = 0;
       
   535         for (int y = 0; y < ThreadCount; ++y) {
       
   536             if (thread_exited[y])
       
   537                         continue;
       
   538             if (rwthread[y].wait(exited > 0 ? 3 : 1000)) {
       
   539                 thread_exited[y] = TRUE;
       
   540                 ++exited;
       
   541             }
       
   542         }
       
   543 
       
   544         QCOMPARE(exited, 1);
       
   545         QCOMPARE(wake_Thread_2::count, ThreadCount - (x + 1));
       
   546     }
       
   547 
       
   548     QCOMPARE(wake_Thread_2::count, 0);
       
   549     }
       
   550 
       
   551     // wake up threads, two at a time
       
   552     for (int i = 0; i < iterations; ++i) {
       
   553     QMutex mutex;
       
   554     QWaitCondition cond;
       
   555 
       
   556         // QMutex
       
   557     wake_Thread thread[ThreadCount];
       
   558     bool thread_exited[ThreadCount];
       
   559 
       
   560     mutex.lock();
       
   561     for (x = 0; x < ThreadCount; ++x) {
       
   562         thread[x].mutex = &mutex;
       
   563         thread[x].cond = &cond;
       
   564         thread_exited[x] = FALSE;
       
   565         thread[x].start();
       
   566         // wait for thread to start
       
   567         QVERIFY(thread[x].started.wait(&mutex, 1000));
       
   568         // make sure wakeups are not queued... if nothing is
       
   569         // waiting at the time of the wakeup, nothing happens
       
   570         QVERIFY(!thread[x].dummy.wait(&mutex, 1));
       
   571     }
       
   572     mutex.unlock();
       
   573 
       
   574     QCOMPARE(wake_Thread::count, ThreadCount);
       
   575 
       
   576     // wake up threads one at a time
       
   577     for (x = 0; x < ThreadCount; x += 2) {
       
   578         mutex.lock();
       
   579         cond.wakeOne();
       
   580         cond.wakeOne();
       
   581         QVERIFY(!cond.wait(&mutex, COND_WAIT_TIME));
       
   582         QVERIFY(!thread[x].dummy.wait(&mutex, 1));
       
   583         QVERIFY(!thread[x + 1].dummy.wait(&mutex, 1));
       
   584         mutex.unlock();
       
   585 
       
   586         int exited = 0;
       
   587         for (int y = 0; y < ThreadCount; ++y) {
       
   588             if (thread_exited[y])
       
   589                         continue;
       
   590             if (thread[y].wait(exited > 0 ? 3 : 1000)) {
       
   591                 thread_exited[y] = TRUE;
       
   592                 ++exited;
       
   593             }
       
   594         }
       
   595 
       
   596         QCOMPARE(exited, 2);
       
   597         QCOMPARE(wake_Thread::count, ThreadCount - (x + 2));
       
   598     }
       
   599 
       
   600     QCOMPARE(wake_Thread::count, 0);
       
   601 
       
   602         // QReadWriteLock
       
   603         QReadWriteLock readWriteLock;
       
   604         wake_Thread_2 rwthread[ThreadCount];
       
   605 
       
   606     readWriteLock.lockForWrite();
       
   607     for (x = 0; x < ThreadCount; ++x) {
       
   608         rwthread[x].readWriteLock = &readWriteLock;
       
   609         rwthread[x].cond = &cond;
       
   610         thread_exited[x] = FALSE;
       
   611         rwthread[x].start();
       
   612         // wait for thread to start
       
   613         QVERIFY(rwthread[x].started.wait(&readWriteLock, 1000));
       
   614         // make sure wakeups are not queued... if nothing is
       
   615         // waiting at the time of the wakeup, nothing happens
       
   616         QVERIFY(!rwthread[x].dummy.wait(&readWriteLock, 1));
       
   617     }
       
   618     readWriteLock.unlock();
       
   619 
       
   620     QCOMPARE(wake_Thread_2::count, ThreadCount);
       
   621 
       
   622     // wake up threads one at a time
       
   623     for (x = 0; x < ThreadCount; x += 2) {
       
   624         readWriteLock.lockForWrite();
       
   625         cond.wakeOne();
       
   626         cond.wakeOne();
       
   627         QVERIFY(!cond.wait(&readWriteLock, COND_WAIT_TIME));
       
   628         QVERIFY(!rwthread[x].dummy.wait(&readWriteLock, 1));
       
   629         QVERIFY(!rwthread[x + 1].dummy.wait(&readWriteLock, 1));
       
   630         readWriteLock.unlock();
       
   631 
       
   632         int exited = 0;
       
   633         for (int y = 0; y < ThreadCount; ++y) {
       
   634             if (thread_exited[y])
       
   635                         continue;
       
   636             if (rwthread[y].wait(exited > 0 ? 3 : 1000)) {
       
   637                 thread_exited[y] = TRUE;
       
   638                 ++exited;
       
   639             }
       
   640         }
       
   641 
       
   642         QCOMPARE(exited, 2);
       
   643         QCOMPARE(wake_Thread_2::count, ThreadCount - (x + 2));
       
   644     }
       
   645 
       
   646     QCOMPARE(wake_Thread_2::count, 0);
       
   647 }
       
   648 }
       
   649 
       
   650 void tst_QWaitCondition::wakeAll()
       
   651 {
       
   652     int x;
       
   653     for (int i = 0; i < iterations; ++i) {
       
   654     QMutex mutex;
       
   655     QWaitCondition cond;
       
   656 
       
   657     // QMutex
       
   658     wake_Thread thread[ThreadCount];
       
   659 
       
   660     mutex.lock();
       
   661     for (x = 0; x < ThreadCount; ++x) {
       
   662         thread[x].mutex = &mutex;
       
   663         thread[x].cond = &cond;
       
   664         thread[x].start();
       
   665         // wait for thread to start
       
   666         QVERIFY(thread[x].started.wait(&mutex, 1000));
       
   667     }
       
   668     mutex.unlock();
       
   669 
       
   670     QCOMPARE(wake_Thread::count, ThreadCount);
       
   671 
       
   672     // wake up all threads at once
       
   673     mutex.lock();
       
   674     cond.wakeAll();
       
   675     QVERIFY(!cond.wait(&mutex, COND_WAIT_TIME));
       
   676     mutex.unlock();
       
   677 
       
   678     int exited = 0;
       
   679     for (x = 0; x < ThreadCount; ++x) {
       
   680         if (thread[x].wait(1000))
       
   681         ++exited;
       
   682     }
       
   683 
       
   684     QCOMPARE(exited, ThreadCount);
       
   685     QCOMPARE(wake_Thread::count, 0);
       
   686 
       
   687     // QReadWriteLock
       
   688     QReadWriteLock readWriteLock;
       
   689     wake_Thread_2 rwthread[ThreadCount];
       
   690 
       
   691     readWriteLock.lockForWrite();
       
   692     for (x = 0; x < ThreadCount; ++x) {
       
   693         rwthread[x].readWriteLock = &readWriteLock;
       
   694         rwthread[x].cond = &cond;
       
   695         rwthread[x].start();
       
   696         // wait for thread to start
       
   697         QVERIFY(rwthread[x].started.wait(&readWriteLock, 1000));
       
   698     }
       
   699     readWriteLock.unlock();
       
   700 
       
   701     QCOMPARE(wake_Thread_2::count, ThreadCount);
       
   702 
       
   703     // wake up all threads at once
       
   704     readWriteLock.lockForWrite();
       
   705     cond.wakeAll();
       
   706     QVERIFY(!cond.wait(&readWriteLock, COND_WAIT_TIME));
       
   707     readWriteLock.unlock();
       
   708 
       
   709     exited = 0;
       
   710     for (x = 0; x < ThreadCount; ++x) {
       
   711         if (rwthread[x].wait(1000))
       
   712         ++exited;
       
   713     }
       
   714 
       
   715     QCOMPARE(exited, ThreadCount);
       
   716     QCOMPARE(wake_Thread_2::count, 0);
       
   717     }
       
   718 }
       
   719 
       
   720 class wait_RaceConditionThread : public QThread
       
   721 {
       
   722 public:
       
   723     wait_RaceConditionThread(QMutex *mutex, QWaitCondition *startup, QWaitCondition *waitCondition,
       
   724                              ulong timeout = ULONG_MAX)
       
   725         : timeout(timeout), returnValue(false), ready(false),
       
   726           mutex(mutex), startup(startup), waitCondition(waitCondition) {}
       
   727 
       
   728     unsigned long timeout;
       
   729     bool returnValue;
       
   730 
       
   731     bool ready;
       
   732 
       
   733     QMutex *mutex;
       
   734     QWaitCondition *startup;
       
   735     QWaitCondition *waitCondition;
       
   736 
       
   737     void run() {
       
   738         mutex->lock();
       
   739 
       
   740         ready = true;
       
   741         startup->wakeOne();
       
   742 
       
   743         returnValue = waitCondition->wait(mutex, timeout);
       
   744 
       
   745         mutex->unlock();
       
   746     }
       
   747 };
       
   748 
       
   749 class wait_RaceConditionThread_2 : public QThread
       
   750 {
       
   751 public:
       
   752     wait_RaceConditionThread_2(QReadWriteLock *readWriteLock,
       
   753                                QWaitCondition *startup,
       
   754                                QWaitCondition *waitCondition,
       
   755                                ulong timeout = ULONG_MAX)
       
   756         : timeout(timeout), returnValue(false), ready(false),
       
   757           readWriteLock(readWriteLock), startup(startup), waitCondition(waitCondition)
       
   758     { }
       
   759 
       
   760     unsigned long timeout;
       
   761     bool returnValue;
       
   762 
       
   763     bool ready;
       
   764 
       
   765     QReadWriteLock *readWriteLock;
       
   766     QWaitCondition *startup;
       
   767     QWaitCondition *waitCondition;
       
   768 
       
   769     void run() {
       
   770         readWriteLock->lockForWrite();
       
   771 
       
   772         ready = true;
       
   773         startup->wakeOne();
       
   774 
       
   775         returnValue = waitCondition->wait(readWriteLock, timeout);
       
   776 
       
   777         readWriteLock->unlock();
       
   778     }
       
   779 };
       
   780 
       
   781 void tst_QWaitCondition::wait_RaceCondition()
       
   782 {
       
   783     {
       
   784         QMutex mutex;
       
   785         QWaitCondition startup;
       
   786         QWaitCondition waitCondition;
       
   787 
       
   788         wait_RaceConditionThread timeoutThread(&mutex, &startup, &waitCondition, 1000),
       
   789             waitingThread1(&mutex, &startup, &waitCondition);
       
   790 
       
   791         timeoutThread.start();
       
   792         waitingThread1.start();
       
   793         mutex.lock();
       
   794 
       
   795         // wait for the threads to start up
       
   796         while (!timeoutThread.ready
       
   797                || !waitingThread1.ready) {
       
   798             startup.wait(&mutex);
       
   799         }
       
   800 
       
   801         QTest::qWait(2000);
       
   802 
       
   803         waitCondition.wakeOne();
       
   804 
       
   805         mutex.unlock();
       
   806 
       
   807         QVERIFY(timeoutThread.wait(5000));
       
   808         QVERIFY(!timeoutThread.returnValue);
       
   809         QVERIFY(waitingThread1.wait(5000));
       
   810         QVERIFY(waitingThread1.returnValue);
       
   811     }
       
   812 
       
   813     {
       
   814         QReadWriteLock readWriteLock;
       
   815         QWaitCondition startup;
       
   816         QWaitCondition waitCondition;
       
   817 
       
   818         wait_RaceConditionThread_2 timeoutThread(&readWriteLock, &startup, &waitCondition, 1000),
       
   819             waitingThread1(&readWriteLock, &startup, &waitCondition);
       
   820 
       
   821         timeoutThread.start();
       
   822         waitingThread1.start();
       
   823         readWriteLock.lockForRead();
       
   824 
       
   825         // wait for the threads to start up
       
   826         while (!timeoutThread.ready
       
   827                || !waitingThread1.ready) {
       
   828             startup.wait(&readWriteLock);
       
   829         }
       
   830 
       
   831         QTest::qWait(2000);
       
   832 
       
   833         waitCondition.wakeOne();
       
   834 
       
   835         readWriteLock.unlock();
       
   836 
       
   837         QVERIFY(timeoutThread.wait(5000));
       
   838         QVERIFY(!timeoutThread.returnValue);
       
   839         QVERIFY(waitingThread1.wait(5000));
       
   840         QVERIFY(waitingThread1.returnValue);
       
   841     }
       
   842 }
       
   843 
       
   844 QTEST_MAIN(tst_QWaitCondition)
       
   845 #include "tst_qwaitcondition.moc"