/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore>
#include <stdio.h>
#include <stdlib.h>
#include <QTimer>
#include <QObject>
//! [0]
const int DataSize = 100000;
const int BufferSize = 8192;
char buffer[BufferSize];
QWaitCondition bufferNotEmpty;
QWaitCondition bufferNotFull;
QMutex mutex;
int numUsedBytes = 0;
//! [0]
//! [1]
class Producer : public QThread
//! [1] //! [2]
{
public:
Producer(QObject *parent = NULL) : QThread(parent)
{
}
void run() override
{
for (int i = 0; i < DataSize; ++i) {
mutex.lock();
if (numUsedBytes == BufferSize)
bufferNotFull.wait(&mutex);
mutex.unlock();
buffer[i % BufferSize] = "ACGT"[QRandomGenerator::global()->bounded(4)];
mutex.lock();
++numUsedBytes;
bufferNotEmpty.wakeAll();
mutex.unlock();
}
}
};
//! [2]
//! [3]
class Consumer : public QThread
//! [3] //! [4]
{
Q_OBJECT
public:
Consumer(QObject *parent = NULL) : QThread(parent)
{
}
void run() override
{
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");
}
signals:
void stringConsumed(const QString &text);
};
//! [4]
class App;
class Api;
QWaitCondition g_doCond;
QMutex g_mutexApp;
class App:public QObject
{
Q_OBJECT
public:
App(){
m_api = nullptr;
}
~App(){
}
void init(Api* api) {
m_api = api;
}
public slots:
void autoRun() {
qDebug() << "entered app autoRun";
QMetaObject::invokeMethod((QObject*)m_api, "doSomething", Qt::QueuedConnection);
g_mutexApp.lock();
qDebug() << "auto run done, lock///";
g_doCond.wait(&g_mutexApp);
qDebug() << "auto run done, unlock///";
g_mutexApp.unlock();
qDebug() << "auto run done, wake up///";
}
private:
Api *m_api;
};
QWaitCondition g_doneCond2;
QMutex g_mutexApi2;
class Api:public QObject
{
Q_OBJECT
public:
Api(){
}
~Api(){
}
public slots:
void doSomething(){
qDebug() << "do ing";
QTimer::singleShot(2000, this, &Api::onDone);
}
void onDone(){
qDebug() << "done";
g_mutexApp.lock();
g_doCond.wakeAll();
g_mutexApp.unlock();
}
};
void test()
{
qDebug() << __FUNCTION__" thread id=" << QThread::currentThreadId();
QThread *threadApp = new QThread();
QThread *threadApi = new QThread();
App *app = new App;
Api *api = new Api;
app->moveToThread(threadApp);
api->moveToThread(threadApi);
threadApi->start();
threadApp->start();
app->init(api);
qDebug() << "start app";
QMetaObject::invokeMethod((QObject*)app, "autoRun", Qt::QueuedConnection);
qDebug() << "test app end.";
threadApp->wait();
threadApi->wait();
threadApp->deleteLater();
threadApi->deleteLater();
app->deleteLater();
api->deleteLater();
}
//! [5]
int main(int argc, char *argv[])
//! [5] //! [6]
{
QCoreApplication app(argc, argv);
/*
Producer producer;
Consumer consumer;
producer.start();
consumer.start();
producer.wait();
consumer.wait();
*/
test();
return app.exec();
}
//! [6]
#include "waitconditions.moc"
Sleep 使用QWaitCondition替换,app 使用 api 实现业务。 api 干活开始,app 线程被阻塞,api 干完后唤醒 app 所在线程。
避免 app sleep 循环占用cpu。
note: mutex 的使用, invkoe 的连接方式, 函数使用 slot 函数