It's strange that Qt framework doesn't have a QBlockingQueue implementation... So i have taken the QQueue, some QtConcurrent stuff and 10 minutes of my free lazy time
So, that's all!
#ifndef BLOCKINGQUEUE_H
#define BLOCKINGQUEUE_H
#include <QQueue>
#include <QMutex>
#include <QWaitCondition>
/*!
@brief A Blocking Queue implementation
@author Alessio 'Slux' Di Fazio
*/
template class BlockingQueue
{
private:
QQueue queue;
QMutex enqueueSerialAccess, dequeueWaitConditionLocker;
QWaitCondition waitBlockingQueueAccess;
public:
/*! Empty constructor */
inline BlockingQueue() {}
/*! Empty destructor */
inline ~BlockingQueue() {};
/*! enqueue thread safe function that wake one blocked thread that wait for dequeue. */
inline void enqueue(const T &t)
{
QMutexLocker locker(&enqueueSerialAccess);
queue.enqueue(t);
waitBlockingQueueAccess.wakeOne();
}
/*! blocking queue thread safe function that block the thread if the queue is empty. */
inline T dequeue()
{
dequeueWaitConditionLocker.lock();
if (queue.isEmpty())
waitBlockingQueueAccess.wait(&dequeueWaitConditionLocker);
T returnVal = queue.dequeue();
dequeueWaitConditionLocker.unlock();
return returnVal;
}
};
#endif // BLOCKINGQUEUE_H
And if you want to test the blocking queue...
#include <QtCore>
#include "BlockingQueue.h"
BlockingQueue blockingQueue;
class Producer : public QThread
{
public:
QString threadName;
Producer(const QString &name) {threadName = name;}
protected:
virtual void run()
{
qDebug() << "Producer" << threadName << "started.";
for(int i=0; i<100; ++i)
{
msleep(5);
QString val = threadName;
val.append(" -> ");
val.append(QString::number(i));
blockingQueue.enqueue(val);
}
}
};
class Consumer : public QThread
{
protected:
virtual void run()
{
qDebug() << "Consumer started.";
Q_FOREVER
{
qDebug() << "Readed queque value: " << blockingQueue.dequeue();
}
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Consumer *consumer = new Consumer();
consumer->start();
for (int i=0; i<100; ++i)
{
Producer *p = new Producer(QString::number(i).prepend("PROD "));
p->start();
}
return a.exec();
}
Slux :)