vendredi 30 juin 2017

c++11 threads: unable to stop thread

I'm learning to use threads in c++11 (I've mostly used threads via some framework but not directly).

Here's a simple class that runs the run() method in a new thread. The start()/stop() method are used for controlling the threads lifecycle:

#include <thread>
#include <mutex>
#include <iostream>
#include <memory>
#include <atomic>
#include <unistd.h>

using namespace std;

class ThreadTest
{
public:
    ThreadTest() : _run(false), _t(nullptr) {}
    void start()
    {   
        lock_guard<mutex> g(_mutex);
        cout << "Starting new thread..." << endl;
        _run = true;
        if (!_t) {
            _t.reset(new thread(&ThreadTest::run, this));
        }
    }

    void stop()
    {   
        lock_guard<mutex> g(_mutex); 
        cout << "Stopping thread..." << endl;
        _run = false;
        if (_t) {
            _t->join();
            _t.reset(nullptr);
        }
    }

    void run()
    {   
        while(true) {
            lock_guard<mutex> g(_mutex);
            if (!_run) {
                return;
            }
            cout << "Running every sec" << endl;
            sleep(1);
        } 
   }

private:
    atomic<bool> _run;
    unique_ptr<thread> _t;
    mutex _mutex;
};

int main()
{
    ThreadTest t;
    t.start();
    cout << "Sleeping for 2 secs..." << endl;
    sleep(2);
    cout << "Done" << endl;
    t.stop();
    return 0;
}

Sample output:

Starting new thread...
Sleeping for 2 secs...
Running every sec
Running every sec
Done
Running every sec
Running every sec
Running every sec
Running every sec

The problem is that the thread does NOT stop after calling stop()! On debugging I found that its stuck in this function trying to acquire the lock _mutex and therefore the _run variable is not set to false yet. I know that since _run is an atomic, I dont strictly need locks here, but I'm trying to understand the usage of locks here.

Shouldn't the mutex be acquired whenever the while loop of run() loops again?

For the life of me I can't explain this trivial issue! :/

Aucun commentaire:

Enregistrer un commentaire