void ThreadServerPool::requestStop(void) { QMutexLocker locker(&this->_mutex); this->_stopRequested = true; // Request stop for all threads client foreach (ThreadClient* threadClient, this->_threadsClient) threadClient->requestStop(); // Wake all threads client which could be blocked on QWaitCondition clientsIsNotEmpty.wakeAll(); // Wait until all threads client stop foreach (ThreadClient* threadClient, this->_threadsClient) threadClient->wait(); // Free client sockets conditionMutex.lock(); clients.clear(); conditionMutex.unlock(); // Interrupt server blocking function if (this->_socketServer != NULL && this->_socketServer->isValid()) { delete this->_socketServer; // Shutdown and close this->_socketServer = NULL; } }
void stop() { m_bQuitRequest=true; m_pDataReady->wakeAll(); wait(); m_bQuitRequest=false; };
GenericSchedulerThread::ThreadStateEnum GenericSchedulerThreadPrivate::resolveState() { GenericSchedulerThread::ThreadStateEnum ret = GenericSchedulerThread::eThreadStateActive; // flag that we have quit the thread { QMutexLocker k(&mustQuitMutex); if (mustQuit) { mustQuit = false; startingThreadAllowed = lastQuitThreadAllowedRestart; ret = GenericSchedulerThread::eThreadStateStopped; // Wake up threads waiting in waitForThreadToQuit mustQuitCond.wakeAll(); } } { QMutexLocker k(&abortRequestedMutex); if (abortRequested > 0) { if (ret == GenericSchedulerThread::eThreadStateActive) { ret = GenericSchedulerThread::eThreadStateAborted; } } } return ret; }
static void PostLoad(const QString &cacheKey) { m_loadingImagesLock.lock(); m_loadingImages.remove(cacheKey); m_loadingImagesCond.wakeAll(); m_loadingImagesLock.unlock(); }
void QtMediaPlayerJNI::WakeUpThread() { while(mutexload==NULL); mutexload->lock(); waitCondition.wakeAll(); mutexload->unlock(); mutexload = NULL; }
void SndThr::gotSound(unsigned id) { (void)id; mut2.lock(); sndDone = true; mut2.unlock(); //Debug() << "EmulApp manual trigger thread will be woken up for trigger " << trig; cond2.wakeAll(); }
void SndThr::triggered(int trig) { (void)trig; mut.lock(); trigDone = true; mut.unlock(); //Debug() << "EmulApp manual trigger thread will be woken up for trigger " << trig; cond.wakeAll(); }
// Wake from executive wait condition (RT-safe). void qmidinetJackMidiThread::sync (void) { if (m_mutex.tryLock()) { m_cond.wakeAll(); m_mutex.unlock(); } #ifdef CONFIG_DEBUG else qDebug("qmidinetJackMidiThread[%p]::sync(): tryLock() failed.", this); #endif }
/// \brief Handles messages received from logging clients /// \param msg The message received (can be multi-part) void LogServerThread::receivedMessage(const QList<QByteArray> &msg) { LogMessage *message = new LogMessage(msg); QMutexLocker lock(&logMsgListMutex); bool wasEmpty = logMsgList.isEmpty(); logMsgList.append(message); if (wasEmpty) logMsgListNotEmpty.wakeAll(); }
void run() { readWriteLock->lockForWrite(); ++count; dummy.wakeOne(); // this wakeup should be lost started.wakeOne(); dummy.wakeAll(); // this one too cond->wait(readWriteLock); --count; readWriteLock->unlock(); }
void run() { mutex->lock(); ++count; dummy.wakeOne(); // this wakeup should be lost started.wakeOne(); dummy.wakeAll(); // this one too cond->wait(mutex); --count; mutex->unlock(); }
void AsyncWorker::assignRequest(QOrganizerAbstractRequest* r) { QMutexLocker lock(&m_lock); Q_ASSERT_X(!m_req, "Worker", "Something is wrong with locking mechanism!"); m_req = r; //either start the thread if is not running or wake up the sleeping thread if (!isRunning()) start(); else m_wait.wakeAll(); }
void AsyncWorker::kill() { { QMutexLocker locker(&m_lock); //mark the exit flag and wake up the thread if is sleeping m_kill = true; m_wait.wakeAll(); } //wait the thread to finish wait(); }
void Consumer1::run() { qDebug() << "Consumer " << m_id << " before wakeall "; if(m_bWakeAll) g_con.wakeAll(); else g_con.wakeOne(); qDebug() << "Consumer " << m_id << " after wakeall"; }
void run() { _qCoreApplication.reset(new QCoreApplication(_dummyArgc, const_cast<char**>(&_dummyArgs[0]))); OsmAnd::initializeInAppThread(); { QMutexLocker scopedLocker(&_qCoreApplicationThreadMutex); wasInitialized = true; _qCoreApplicationThreadWaitCondition.wakeAll(); } QCoreApplication::exec(); OsmAnd::releaseInAppThread(); _qCoreApplication.reset(); }
void Producer::run() { for (int i = 0; i < DataSize; ++i) { mutex.lock(); if (numUsedBytes == BufferSize) { bufferEmpty.wait(&mutex); } buffer[i % BufferSize] = numUsedBytes; ++numUsedBytes; bufferFull.wakeAll(); mutex.unlock(); } }
void Consumer::run() { for (int i = 0; i < DataSize; ++i) { mutex.lock(); if (numUsedBytes == 0) bufferNotEmpty.wait(&mutex); mutex.unlock(); fprintf(stderr, "%c", buffer[i % BufferSize]); mutex.lock(); --numUsedBytes; bufferNotFull.wakeAll(); mutex.unlock(); } fprintf(stderr, "\n"); }
void GfxImageLoaderEngine::load(GfxImageLoader *out, const QString &filename, const QList<QSize> &sizes) { lock.lock(); bool wasEmpty = ops.isEmpty(); Op op; op.filename = filename; op.sizes = sizes; op.id = id++; op.out = out; ops.insert(out, op); if(wasEmpty) wait.wakeAll(); lock.unlock(); }
void run() { qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); for (int i = 0; i < DataSize; ++i) { mutex.lock(); if (numUsedBytes == BufferSize) bufferNotFull.wait(&mutex); mutex.unlock(); buffer[i % BufferSize] = "ACGT"[(int)qrand() % 4]; mutex.lock(); ++numUsedBytes; bufferNotEmpty.wakeAll(); mutex.unlock(); } }
void OsmAnd::Concurrent::Dispatcher::invoke(const Delegate method) { assert(method != nullptr); QMutex waitMutex; QWaitCondition waitCondition; invokeAsync([&waitCondition, &waitMutex, method] { method(); { QMutexLocker scopedLocker(&waitMutex); waitCondition.wakeAll(); } }); { QMutexLocker scopedLocker(&waitMutex); REPEAT_UNTIL(waitCondition.wait(&waitMutex)); } }
void SimulationLocker::lockFor(long msecs) { m_lockDuration = msecs<0 ? 0 : msecs; adjustLockDuration(); auto startPause = [this]() { auto conn = connect(this, SIGNAL(_startIt()), &m_lockTimer, SLOT(start())); emit _startIt(); // make sure timer starts in gui thread QObject::disconnect(conn); }; QMutex mutex; QWaitCondition condition; auto connexion = connect(&m_lockTimer, &QTimer::timeout, [&condition](){condition.wakeAll();}); mutex.lock(); startPause(); // to make sure timer starts in this' thread (gui thread) condition.wait(&mutex); mutex.unlock(); QObject::disconnect(connexion); }
QImage QtZLWorker::loadCover(const QString &id) { QByteArray pathRaw = QByteArray::fromBase64(id.toLatin1()); QMutex mutex; QWaitCondition cond; QImage result; bool ready = false; auto work = [pathRaw, &result, &ready, &mutex, &cond] () { ZLFile file(std::string(pathRaw.constData(), pathRaw.size())); shared_ptr<FormatPlugin> plugin = PluginCollection::Instance().plugin(file, false); if (!plugin.isNull()) { shared_ptr<const ZLImage> image = plugin->coverImage(file); if (!image.isNull()) { shared_ptr<ZLImageData> data = ZLImageManager::Instance().imageData(*image); if (!data.isNull()) result = static_cast<QtZLImageData &>(*data).toImage(); } } QMutexLocker locker(&mutex); ready = true; cond.wakeAll(); }; selfMethod.invoke(this, Qt::QueuedConnection, Q_ARG(QtZLWork, work)); QMutexLocker locker(&mutex); while (!ready) cond.wait(&mutex); return result; }
void run() { SireError::setThreadString("Promise"); SireMaths::seed_qrand(); QMutexLocker lkr(&datamutex); //get a local copy of the node Node my_node = node; lkr.unlock(); //wait until the job has finished my_node.wait(); //the node has finished - grab the result and //drop our copy of the node WorkPacket my_result = my_node.result(); if (my_result.isNull()) { //where did the result go??? my_result = ErrorPacket( SireError::program_bug( QObject::tr( "There was no result from the running calculation!!!"), CODELOC ) ); } //copy the result to the promise lkr.relock(); result_packet = my_result; //drop the reference to the node node = Node(); //wake anyone waiting for a result waiter.wakeAll(); }
bool QgsWfsRequest::sendGET( const QUrl &url, bool synchronous, bool forceRefresh, bool cache ) { abort(); // cancel previous mIsAborted = false; mTimedout = false; mGotNonEmptyResponse = false; mErrorMessage.clear(); mErrorCode = QgsWfsRequest::NoError; mForceRefresh = forceRefresh; mResponse.clear(); QUrl modifiedUrl( url ); // Specific code for testing if ( modifiedUrl.toString().contains( QLatin1String( "fake_qgis_http_endpoint" ) ) ) { // Just for testing with local files instead of http:// resources QString modifiedUrlString = modifiedUrl.toString(); // Qt5 does URL encoding from some reason (of the FILTER parameter for example) modifiedUrlString = QUrl::fromPercentEncoding( modifiedUrlString.toUtf8() ); QgsDebugMsgLevel( QStringLiteral( "Get %1" ).arg( modifiedUrlString ), 4 ); modifiedUrlString = modifiedUrlString.mid( QStringLiteral( "http://" ).size() ); QString args = modifiedUrlString.mid( modifiedUrlString.indexOf( '?' ) ); if ( modifiedUrlString.size() > 256 ) { args = QCryptographicHash::hash( args.toUtf8(), QCryptographicHash::Md5 ).toHex(); } else { args.replace( QLatin1String( "?" ), QLatin1String( "_" ) ); args.replace( QLatin1String( "&" ), QLatin1String( "_" ) ); args.replace( QLatin1String( "<" ), QLatin1String( "_" ) ); args.replace( QLatin1String( ">" ), QLatin1String( "_" ) ); args.replace( QLatin1String( "'" ), QLatin1String( "_" ) ); args.replace( QLatin1String( "\"" ), QLatin1String( "_" ) ); args.replace( QLatin1String( " " ), QLatin1String( "_" ) ); args.replace( QLatin1String( ":" ), QLatin1String( "_" ) ); args.replace( QLatin1String( "/" ), QLatin1String( "_" ) ); args.replace( QLatin1String( "\n" ), QLatin1String( "_" ) ); } #ifdef Q_OS_WIN // Passing "urls" like "http://c:/path" to QUrl 'eats' the : after c, // so we must restore it if ( modifiedUrlString[1] == '/' ) { modifiedUrlString = modifiedUrlString[0] + ":/" + modifiedUrlString.mid( 2 ); } #endif modifiedUrlString = modifiedUrlString.mid( 0, modifiedUrlString.indexOf( '?' ) ) + args; QgsDebugMsgLevel( QStringLiteral( "Get %1 (after laundering)" ).arg( modifiedUrlString ), 4 ); modifiedUrl = QUrl::fromLocalFile( modifiedUrlString ); } QgsDebugMsgLevel( QStringLiteral( "Calling: %1" ).arg( modifiedUrl.toDisplayString( ) ), 4 ); QNetworkRequest request( modifiedUrl ); if ( !mUri.auth().setAuthorization( request ) ) { mErrorCode = QgsWfsRequest::NetworkError; mErrorMessage = errorMessageFailedAuth(); QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) ); return false; } if ( cache ) { request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, forceRefresh ? QNetworkRequest::AlwaysNetwork : QNetworkRequest::PreferCache ); request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true ); } QWaitCondition waitCondition; QMutex waitConditionMutex; bool threadFinished = false; bool success = false; std::function<void()> downloaderFunction = [ this, request, synchronous, &waitConditionMutex, &waitCondition, &threadFinished, &success ]() { if ( QThread::currentThread() != QgsApplication::instance()->thread() ) QgsNetworkAccessManager::instance( Qt::DirectConnection ); success = true; mReply = QgsNetworkAccessManager::instance()->get( request ); mReply->setReadBufferSize( READ_BUFFER_SIZE_HINT ); if ( !mUri.auth().setAuthorizationReply( mReply ) ) { mErrorCode = QgsWfsRequest::NetworkError; mErrorMessage = errorMessageFailedAuth(); QgsMessageLog::logMessage( mErrorMessage, tr( "WFS" ) ); waitCondition.wakeAll(); success = false; } else { // We are able to use direct connection here, because we // * either run on the thread mReply lives in, so DirectConnection is standard and safe anyway // * or the owner thread of mReply is currently not doing anything because it's blocked in future.waitForFinished() (if it is the main thread) connect( mReply, &QNetworkReply::finished, this, &QgsWfsRequest::replyFinished, Qt::DirectConnection ); connect( mReply, &QNetworkReply::downloadProgress, this, &QgsWfsRequest::replyProgress, Qt::DirectConnection ); if ( synchronous ) { auto resumeMainThread = [&waitConditionMutex, &waitCondition]() { waitConditionMutex.lock(); waitCondition.wakeAll(); waitConditionMutex.unlock(); waitConditionMutex.lock(); waitCondition.wait( &waitConditionMutex ); waitConditionMutex.unlock(); }; connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::authenticationRequired, this, resumeMainThread, Qt::DirectConnection ); connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::proxyAuthenticationRequired, this, resumeMainThread, Qt::DirectConnection ); #ifndef QT_NO_SSL connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::sslErrors, this, resumeMainThread, Qt::DirectConnection ); #endif QEventLoop loop; connect( this, &QgsWfsRequest::downloadFinished, &loop, &QEventLoop::quit, Qt::DirectConnection ); loop.exec(); } } waitConditionMutex.lock(); threadFinished = true; waitCondition.wakeAll(); waitConditionMutex.unlock(); }; if ( synchronous && QThread::currentThread() == QApplication::instance()->thread() ) { std::unique_ptr<DownloaderThread> downloaderThread = qgis::make_unique<DownloaderThread>( downloaderFunction ); downloaderThread->start(); while ( true ) { waitConditionMutex.lock(); if ( threadFinished ) { waitConditionMutex.unlock(); break; } waitCondition.wait( &waitConditionMutex ); // If the downloader thread wakes us (the main thread) up and is not yet finished // he needs the authentication to run. // The processEvents() call gives the auth manager the chance to show a dialog and // once done with that, we can wake the downloaderThread again and continue the download. if ( !threadFinished ) { waitConditionMutex.unlock(); QgsApplication::instance()->processEvents(); waitConditionMutex.lock(); waitCondition.wakeAll(); waitConditionMutex.unlock(); } else { waitConditionMutex.unlock(); } } // wait for thread to gracefully exit downloaderThread->wait(); } else { downloaderFunction(); } return success && mErrorMessage.isEmpty(); }
void tst_QWaitCondition::wakeAll() { int x; for (int i = 0; i < iterations; ++i) { QMutex mutex; QWaitCondition cond; // QMutex wake_Thread thread[ThreadCount]; mutex.lock(); for (x = 0; x < ThreadCount; ++x) { thread[x].mutex = &mutex; thread[x].cond = &cond; thread[x].start(); // wait for thread to start QVERIFY(thread[x].started.wait(&mutex, 1000)); } mutex.unlock(); QCOMPARE(wake_Thread::count, ThreadCount); // wake up all threads at once mutex.lock(); cond.wakeAll(); QVERIFY(!cond.wait(&mutex, COND_WAIT_TIME)); mutex.unlock(); int exited = 0; for (x = 0; x < ThreadCount; ++x) { if (thread[x].wait(1000)) ++exited; } QCOMPARE(exited, ThreadCount); QCOMPARE(wake_Thread::count, 0); // QReadWriteLock QReadWriteLock readWriteLock; wake_Thread_2 rwthread[ThreadCount]; readWriteLock.lockForWrite(); for (x = 0; x < ThreadCount; ++x) { rwthread[x].readWriteLock = &readWriteLock; rwthread[x].cond = &cond; rwthread[x].start(); // wait for thread to start QVERIFY(rwthread[x].started.wait(&readWriteLock, 1000)); } readWriteLock.unlock(); QCOMPARE(wake_Thread_2::count, ThreadCount); // wake up all threads at once readWriteLock.lockForWrite(); cond.wakeAll(); QVERIFY(!cond.wait(&readWriteLock, COND_WAIT_TIME)); readWriteLock.unlock(); exited = 0; for (x = 0; x < ThreadCount; ++x) { if (rwthread[x].wait(1000)) ++exited; } QCOMPARE(exited, ThreadCount); QCOMPARE(wake_Thread_2::count, 0); } }
void SendDataThread::sendData(const QByteArray &data) { QMutexLocker locker(&m_DataMutex); m_DataList.push_back(data); m_DataCondition.wakeAll(); }
void tst_QWaitCondition::wait_QReadWriteLock() { { QReadWriteLock readWriteLock(QReadWriteLock::Recursive); QWaitCondition waitCondition; // ensure that the lockForRead is correctly restored readWriteLock.lockForRead(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); QVERIFY(!readWriteLock.tryLockForWrite()); QVERIFY(readWriteLock.tryLockForRead()); readWriteLock.unlock(); QVERIFY(!readWriteLock.tryLockForWrite()); readWriteLock.unlock(); QVERIFY(readWriteLock.tryLockForWrite()); readWriteLock.unlock(); } { QReadWriteLock readWriteLock(QReadWriteLock::Recursive); QWaitCondition waitCondition; // ensure that the lockForWrite is correctly restored readWriteLock.lockForWrite(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); QVERIFY(!readWriteLock.tryLockForRead()); QVERIFY(readWriteLock.tryLockForWrite()); readWriteLock.unlock(); QVERIFY(!readWriteLock.tryLockForRead()); readWriteLock.unlock(); QVERIFY(readWriteLock.tryLockForRead()); readWriteLock.unlock(); } int x; for (int i = 0; i < iterations; ++i) { { QReadWriteLock readWriteLock; QWaitCondition waitCondition; readWriteLock.lockForRead(); waitCondition.wakeOne(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); waitCondition.wakeAll(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); readWriteLock.unlock(); } { QReadWriteLock readWriteLock; QWaitCondition waitCondition; readWriteLock.lockForWrite(); waitCondition.wakeOne(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); waitCondition.wakeAll(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); readWriteLock.unlock(); } { // test multiple threads waiting on separate wait conditions wait_QReadWriteLock_Thread_1 thread[ThreadCount]; for (x = 0; x < ThreadCount; ++x) { thread[x].readWriteLock.lockForRead(); thread[x].start(); // wait for thread to start QVERIFY(thread[x].cond.wait(&thread[x].readWriteLock, 1000)); thread[x].readWriteLock.unlock(); } for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].isRunning()); QVERIFY(!thread[x].isFinished()); } for (x = 0; x < ThreadCount; ++x) { thread[x].readWriteLock.lockForRead(); thread[x].cond.wakeOne(); thread[x].readWriteLock.unlock(); } for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].wait(1000)); } } { // test multiple threads waiting on a wait condition QReadWriteLock readWriteLock; QWaitCondition cond1, cond2; wait_QReadWriteLock_Thread_2 thread[ThreadCount]; readWriteLock.lockForWrite(); for (x = 0; x < ThreadCount; ++x) { thread[x].readWriteLock = &readWriteLock; thread[x].cond = (x < ThreadCount / 2) ? &cond1 : &cond2; thread[x].start(); // wait for thread to start QVERIFY(thread[x].started.wait(&readWriteLock, 1000)); } readWriteLock.unlock(); for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].isRunning()); QVERIFY(!thread[x].isFinished()); } readWriteLock.lockForWrite(); cond1.wakeAll(); cond2.wakeAll(); readWriteLock.unlock(); for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].wait(1000)); } } } }
void tst_QWaitCondition::wait_QMutex() { int x; for (int i = 0; i < iterations; ++i) { { QMutex mutex; QWaitCondition cond; mutex.lock(); cond.wakeOne(); QVERIFY(!cond.wait(&mutex, 1)); cond.wakeAll(); QVERIFY(!cond.wait(&mutex, 1)); mutex.unlock(); } { // test multiple threads waiting on separate wait conditions wait_QMutex_Thread_1 thread[ThreadCount]; for (x = 0; x < ThreadCount; ++x) { thread[x].mutex.lock(); thread[x].start(); // wait for thread to start QVERIFY(thread[x].cond.wait(&thread[x].mutex, 1000)); thread[x].mutex.unlock(); } for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].isRunning()); QVERIFY(!thread[x].isFinished()); } for (x = 0; x < ThreadCount; ++x) { thread[x].mutex.lock(); thread[x].cond.wakeOne(); thread[x].mutex.unlock(); } for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].wait(1000)); } } { // test multiple threads waiting on a wait condition QMutex mutex; QWaitCondition cond1, cond2; wait_QMutex_Thread_2 thread[ThreadCount]; mutex.lock(); for (x = 0; x < ThreadCount; ++x) { thread[x].mutex = &mutex; thread[x].cond = (x < ThreadCount / 2) ? &cond1 : &cond2; thread[x].start(); // wait for thread to start QVERIFY(thread[x].started.wait(&mutex, 1000)); } mutex.unlock(); for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].isRunning()); QVERIFY(!thread[x].isFinished()); } mutex.lock(); cond1.wakeAll(); cond2.wakeAll(); mutex.unlock(); for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].wait(1000)); } } } }
void tst_QWaitCondition::wait_QReadWriteLock() { { QReadWriteLock readWriteLock(QReadWriteLock::Recursive); QWaitCondition waitCondition; // ensure that the lockForRead is correctly restored readWriteLock.lockForRead(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); QVERIFY(!readWriteLock.tryLockForWrite()); QVERIFY(readWriteLock.tryLockForRead()); readWriteLock.unlock(); QVERIFY(!readWriteLock.tryLockForWrite()); readWriteLock.unlock(); QVERIFY(readWriteLock.tryLockForWrite()); readWriteLock.unlock(); } { QReadWriteLock readWriteLock(QReadWriteLock::Recursive); QWaitCondition waitCondition; // ensure that the lockForWrite is correctly restored readWriteLock.lockForWrite(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); QVERIFY(!readWriteLock.tryLockForRead()); QVERIFY(readWriteLock.tryLockForWrite()); readWriteLock.unlock(); QVERIFY(!readWriteLock.tryLockForRead()); readWriteLock.unlock(); QVERIFY(readWriteLock.tryLockForRead()); readWriteLock.unlock(); } int x; for (int i = 0; i < iterations; ++i) { { QReadWriteLock readWriteLock; QWaitCondition waitCondition; readWriteLock.lockForRead(); waitCondition.wakeOne(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); waitCondition.wakeAll(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); readWriteLock.unlock(); } { QReadWriteLock readWriteLock; QWaitCondition waitCondition; readWriteLock.lockForWrite(); waitCondition.wakeOne(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); waitCondition.wakeAll(); QVERIFY(!waitCondition.wait(&readWriteLock, 1)); readWriteLock.unlock(); } { // test multiple threads waiting on separate wait conditions wait_QReadWriteLock_Thread_1 thread[ThreadCount]; for (x = 0; x < ThreadCount; ++x) { thread[x].readWriteLock.lockForRead(); thread[x].start(); // wait for thread to start #if defined(Q_OS_SYMBIAN) && defined(Q_CC_WINSCW) // Symbian emulator startup simultaneously with this thread causes additional delay QVERIFY(thread[x].cond.wait(&thread[x].readWriteLock, 10000)); #else QVERIFY(thread[x].cond.wait(&thread[x].readWriteLock, 1000)); #endif thread[x].readWriteLock.unlock(); } for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].isRunning()); QVERIFY(!thread[x].isFinished()); } for (x = 0; x < ThreadCount; ++x) { thread[x].readWriteLock.lockForRead(); thread[x].cond.wakeOne(); thread[x].readWriteLock.unlock(); } for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].wait(1000)); } } { // test multiple threads waiting on a wait condition QReadWriteLock readWriteLock; QWaitCondition cond1, cond2; wait_QReadWriteLock_Thread_2 thread[ThreadCount]; readWriteLock.lockForWrite(); for (x = 0; x < ThreadCount; ++x) { thread[x].readWriteLock = &readWriteLock; thread[x].cond = (x < ThreadCount / 2) ? &cond1 : &cond2; thread[x].start(); // wait for thread to start QVERIFY(thread[x].started.wait(&readWriteLock, 1000)); } readWriteLock.unlock(); for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].isRunning()); QVERIFY(!thread[x].isFinished()); } readWriteLock.lockForWrite(); cond1.wakeAll(); cond2.wakeAll(); readWriteLock.unlock(); for (x = 0; x < ThreadCount; ++x) { QVERIFY(thread[x].wait(1000)); } } } }
void ModelPropertyAnimation::trigger(QAbstractAnimation *animation, bool synchrone, DeletionContext deletionContext) { /* The connexion below won't delete indefinitely looping animation. * To avoid memory leaks, the deletionContext paramater is introduced. */ connect(animation, &QAbstractAnimation::finished, [=](){animation->deleteLater();}); /* Considering what's stated in Qt's doc about Qt::AutoConnection behaviour * (see QObject::connect), we need to make sure * ESPECIALLY WHEN this function is called from a thread other than the gui-thread: * from an algorithm thread for instance, * that the animation passed as parameter leaves in the gui-thread, * so that it can perform flawlessly. * * Indeed, IN THAT CASE, performing a direct call to QAbstractAnimation::start causes the animation * not to perform in the way it should. So we first move it to the gui-thread and then * emit a signal which finally triggers its execution. * * This isn't probably the best way to address this issue, but it works. */ // connect(this, &ModelPropertyAnimation::_startIt, animation, &QAbstractAnimation::start); // the previous syntax doesn't work due to argument count mismatching. connect(this, SIGNAL(_startIt()), animation, SLOT(start())); animation->moveToThread(QApplication::instance()->thread()); auto startAnimation = [=]() { // define a function that will start the animation emit _startIt(); // disconnect the signal, to make sure any further emission is ignored. disconnect(this, SIGNAL(_startIt()), animation, SLOT(start())); }; QThread *t = nullptr; switch(deletionContext) { case None: break; case ThisThread: t = thread(); break; case GuiThread: t = QApplication::instance()->thread(); break; } if(t) { connect(t, &QThread::finished, animation, &QAbstractAnimation::deleteLater); } if(!synchrone) { startAnimation(); } else { QMutex mutex; QWaitCondition condition; auto connexion = connect(animation, &QAbstractAnimation::finished, [&condition](){condition.wakeAll();}); mutex.lock(); startAnimation(); condition.wait(&mutex); mutex.unlock(); disconnect(connexion); } }