I am new to C++ and to threading, so I'm sorry if my code is bad. I'm here to get it better and to learn. Any kind of advice (both on C++ style, on Qt usage, or on threading handling) is welcome. Please feel free to comment anything, also if the question has to be reformulated.I have this problem:one thread that grab frames from a video/web camsome (let's say 3) threads that take the last grabbed frame, do some computer vision analysis, and display it back in the main gui. Each computation thread could have different computation time (because of computation-heavy algorithm like optical flow or similar)There are few important things I want to care about:the threads must run in parallel (that's why I used the threads)threads takes only the last frame depending on their own job, so if a thread has some heavy optical flow computation, it will take only frames (let's say 1, 15, 21, 30). Instead, a light computation that does only frame differencing will take all frames 1, 2, 3, 4,..I need a way to stop it and restart it. Let's say that I have 3 video to analyze, I want to do the first, wait for everything is finished, to the second, etc..I have done a little prototype that works with int as a shared resource, and not with a frame.  I will use opencv, cv::Mat that are basically containers for uchar array where each uchar represents a pixel.I think that this is a working prototype, but I'm very scared about threading.  I've never done something with multithreading, I don't understand the problems well, and I don't know how to test it correctly.I'm going to copy the files here, but the project is also on bitbucket.P.S. If it's worth something, I'm using Qt 4.8 with QtCreator 2.8 under Mac OS/X 10.8, but should be super cross-compiling as I'm just using Qt objects.main.cpp:#include <QApplication>#include mainwidget.hint main(int argc, char *argv[]){    QApplication a(argc, argv);    MainWidget w;    w.show();    return a.exec();}mainwidget.h:#ifndef MAINWIDGET_H#define MAINWIDGET_H#include <QWidget>#include <QLabel>#include <QCloseEvent>#include <QKeyEvent>#include <QVBoxLayout>#include resources.h#include producer.h#include consumer.hclass MainWidget : public QWidget{    Q_OBJECTpublic:    //------------------------------------------------------------------ ctor dtor    explicit MainWidget(QWidget *parent = 0) : QWidget(parent) {        initGUI();        initProducer();        initConsumers();    }    ~MainWidget()    {    }    //------------------------------------------------------------------ 1 prod, n cons    void initProducer()    {        producer = new Producer(&r);        connect(producer, SIGNAL(newFrame(int)),                this, SLOT(showProducer(int)));        connect(producer, SIGNAL(finished()),                producer, SLOT(deleteLater()));        producer->start();    }    void initConsumers()    {        consumerCounter = 0;        consumer1 = new Consumer(1, &r);        connect(consumer1, SIGNAL(newComputation(int)),                this, SLOT(showConsumer1(int)));        connect(consumer1, SIGNAL(finished()),                consumer1, SLOT(deleteLater()));        connect(consumer1, SIGNAL(destroyed()),                this, SLOT(incrementConsumerCounter()));        consumer2 = new Consumer(2, &r);        connect(consumer2, SIGNAL(newComputation(int)),                this, SLOT(showConsumer2(int)));        connect(consumer2, SIGNAL(finished()),                consumer2, SLOT(deleteLater()));        connect(consumer2, SIGNAL(destroyed()),                this, SLOT(incrementConsumerCounter()));        consumer3 = new Consumer(3, &r);        connect(consumer3, SIGNAL(newComputation(int)),                this, SLOT(showConsumer3(int)));        connect(consumer3, SIGNAL(finished()),                consumer3, SLOT(deleteLater()));        connect(consumer3, SIGNAL(destroyed()),                this, SLOT(incrementConsumerCounter()));        consumer1->start();        consumer2->start();        consumer3->start();    }    void stopProducer() {        producer->stopProduce();    }    void stopConsumers() {        consumer1->stopConsume();        consumer2->stopConsume();        consumer3->stopConsume();    }    void stopAll()    {        stopProducer();        stopConsumers();        qDebug() << wake all!;        r.waitCondition.wakeAll();    }    //------------------------------------------------------------------ gui    void initGUI() {        QVBoxLayout *l = new QVBoxLayout;        this->producerLabel = new QLabel;        l->addWidget(producerLabel);        this->consumer1Label = new QLabel;        l->addWidget(consumer1Label);        this->consumer2Label = new QLabel;        l->addWidget(consumer2Label);        this->consumer3Label = new QLabel;        l->addWidget(consumer3Label);        this->setLayout(l);    }    void keyPressEvent(QKeyEvent* event) {        if(event->key() == Qt::Key_S) {            qDebug() << pressed s, stop all;            stopAll();        }        if(event->key() == Qt::Key_R) {            qDebug() << pressed r, restart all;            initProducer();            initConsumers();        }    }    void closeEvent(QCloseEvent * event)    {        emit shutdown();        this->close();    }private:    QLabel *producerLabel;    QLabel *consumer1Label;    QLabel *consumer2Label;    QLabel *consumer3Label;    Resources r;    Producer *producer;    Consumer *consumer1;    Consumer *consumer2;    Consumer *consumer3;    int consumerCounter;private slots:    void showProducer(int n) {        this->producerLabel->setText(QString(Producer: %1).arg(n));    }    void showConsumer1(int n) {        this->consumer1Label->setText(QString(Consumer1: %1).arg(n));    }    void showConsumer2(int n) {        this->consumer2Label->setText(QString(Consumer2: %1).arg(n));    }    void showConsumer3(int n) {        this->consumer3Label->setText(QString(Consumer3: %1).arg(n));    }    void incrementConsumerCounter() {        consumerCounter++;        if(consumerCounter==3) {            qDebug() << ..... could restart!;            initProducer();            initConsumers();        }    }signals:    void shutdown();};#endif // MAINWIDGET_Hresources.h:#ifndef RESOURCES_H#define RESOURCES_H#include <QDebug>#include <QReadWriteLock>#include <QWaitCondition>class Resources {public:    Resources() {        qDebug() << Resources > ctor;        lastFrame = 0;    }    ~Resources() {        qDebug() << Resources > dtor;    }    int lastFrame;    QReadWriteLock lastFrame_read;    QReadWriteLock lastFrame_write;    QWaitCondition waitCondition;};#endif // RESOURCES_Hproducer.h:#ifndef PRODUCER_H#define PRODUCER_H#include <QDebug>#include <QThread>#include <QMutex>#include <QReadWriteLock>#include <QWaitCondition>#include resources.hclass Producer : public QThread{    Q_OBJECTpublic:    explicit Producer(Resources *r, QObject *parent = 0) :        QThread(parent),        abort(false)    {        qDebug() << producer > ctor;        frameCount = 0;        this->r = r;    }    ~Producer() {        qDebug() << Producer dtor;        stopProduce();        wait();    }    void stopProduce() {        abortMutex.lock();        abort = true;        abortMutex.unlock();    }protected:    Resources *r;    int frameCount;    void produce()    {        frameCount++;        r->lastFrame = frameCount;        qDebug() << QString(Producing: %1).arg(frameCount);        emit newFrame(frameCount);    }    void run()    {        forever {            abortMutex.lock();            if(abort) {                abortMutex.unlock();                break;            } abortMutex.unlock();            r->lastFrame_read.lockForRead();            produce();            r->waitCondition.wakeAll();            r->lastFrame_read.unlock();            msleep(200);        }        emit finished();    }private:    QMutex abortMutex;    bool abort;signals:    void newFrame(int);};#endif // PRODUCER_Hconsumer.h:#ifndef CONSUMER_H#define CONSUMER_H#include <QDebug>#include <QThread>#include <QMutex>#include <QWaitCondition>#include <QReadWriteLock>#include <QString>#include resources.hclass Consumer : public QThread{    Q_OBJECTpublic:    Consumer(int id, Resources *r, QObject *parent=0):        QThread(parent),        abort(false)    {        this->r = r;        this->id = id;    }    ~Consumer() {        qDebug() << QString(Consumer %1 dtor).arg(id);        stopConsume();        wait();    }    void stopConsume() {        abortMutex.lock();        abort = true;        abortMutex.unlock();    }protected:    Resources *r;    int id;    int consumeMessage(int val)    {        qDebug() << QString(#%1 Consuming : %2).arg(id).arg(val);        msleep(1000*id);        emit newComputation(val);        return val;    }    void run()    {        forever {            r->lastFrame_read.lockForRead();            consumeMessage(r->lastFrame);            r->lastFrame_read.unlock();            // I think that this check MUST be done here:            // between the consume and the wait            abortMutex.lock();            if(abort) {                abortMutex.unlock();                break;            } abortMutex.unlock();            qDebug() << QString(Consumer %1: going to sleep).arg(id);            r->waitCondition.wait(&r->lastFrame_read);            qDebug() << QString(Consumer %1: awake).arg(id);        }        emit finished();    }private:    QMutex abortMutex;    bool abort;signals:    void newComputation(int);    void finished();};#endif // CONSUMER_H
1 producer, n consumer with QThread
c++;beginner;multithreading;qt;producer consumer