C++11 thread wait

671 Views Asked by At

The Thread.h class implements run method like Thread class in Java, so every class that inherits Thread implements run.

In example below run two thread: Producer and Reader, first (Producer) print a counter in an infinite cycle, second thread (Reader) 1) call wait on Produce, 2) write some int and 3) weakup Produce with notify method. Wait uses a condition_variable variable.

The problem is "producer->wait();" inside Reader::run method doesn't block producer and it continues to write,what's wrong?

compile with

g++ -std=c++11 -pthread main.cpp

thanks in advance

//in main.cpp
int main() {
    Producer p ;
    Reader r ( &p );
    p.start();
    r.start();
    p.join();
    r.join();
    cout << "end" << endl << flush;
}

classes:

// in main.cpp
#include <iostream>
#include <unistd.h>
#include "Thread.h"
class Producer : public Thread {
public:
    Producer() {i = 0;}

    virtual void run() ;
private:
    int i;
};
void Producer::run() {
    while ( 1 ) {
        usleep ( 1000 );
        cout << "Producer count: " << i++ << endl << flush;
    };
};

reader class

// in main.cpp
class Reader : public Thread {
public:
    Reader ( Producer* p ) {producer = p; i = 0;}

virtual void run() ;
private:
    int i;
    Producer* producer;
};
void Reader::run() {
    while ( 1 ) {
        usleep ( 1000 );
        i++;
        if ( ! ( i % 1000 ) ) {
            cout << "waiting Producer" << endl << flush;
            producer->wait();
            cout << "write 10000 int" << endl << flush;
            for ( int k = 0; k < 1000; k++ ) {
                usleep ( 1000 );
                cout << "                     Reader: count " << k << endl << flush;
            }

            producer->notify();
        }
    };
};

Thread.h:

#ifndef THREAD_H_
#define THREAD_H_
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;

class Runnable {
public:
    virtual void run() = 0;
};

class Thread: virtual public Runnable {
private:
    mutex mtx;
    condition_variable cv;
    thread* theThread;
    Runnable * _runnable;
    Runnable * execRunnable;

    static void * __run ( void * cthis ) {
        static_cast<Runnable*> ( cthis )->run();
        return nullptr;
    }

public:
    Thread() :
        _runnable ( nullptr ) {
        theThread = nullptr;
        execRunnable = this;
    }

    virtual ~Thread() {
        if ( theThread ) {
            theThread->detach();
           delete theThread;
            theThread = nullptr;
        }
    }

void wait ( ) {
    unique_lock<std::mutex> lk ( mtx );
    cv.wait ( lk );
}

void notify() {
    cv.notify_all();
}

void start() {
    if ( this->_runnable != nullptr ) {
        execRunnable = this->_runnable;
    }

    if ( theThread ) {
        delete theThread;
    }

    theThread = new thread ( __run, execRunnable );
}

void join() {
    if ( theThread ) {
        theThread->join();
        delete theThread;
        theThread = nullptr;
    }
}

bool isJoinable() {
    return theThread->joinable();
}

void stop() {
    if ( theThread ) {
        theThread->detach();
        delete theThread;
        theThread = nullptr;
    }
}

};
#endif
1

There are 1 best solutions below

0
On

You can't stop the producer thread just like that. You need to set some variable from your reader thread and test its value within the producer. Then producer can call wait() and will continue only after the reader has called notify(). BTW. endl also does flush, no need to call it again.