mardi 12 février 2019

c++ class objects in concurrent threads

I tried to launch a class who has a running thread. When I create the objects it creates a bad group of objects. I really don't understand what is happening. The idea is create 10 objects with their threads and get the messages from the thread f2. I need one queue by worked thread by specs. I use mutex because I thing c++ std:queue is not thread-safe. The problem is when main is running It shows like most of the objects are the same. I post the code:

class classOne {
public:
    classOne(int n, std::shared_ptr<std::mutex> prompr_mtx_ptr);
    ~classOne();

    int m_id;
    bool m_stop;
    std::shared_ptr<std::mutex> m_mtx;
    std::shared_ptr<std::thread> m_classOne_thread;
    std::shared_ptr<std::mutex> m_prompr_mtx_ptr;
    std::shared_ptr<std::queue<std::string>> m_queue;

    void classOne_thread_body();
};

classOne::~classOne() {

}

classOne::classOne(int n, std::shared_ptr<std::mutex> prompr_mtx_ptr):
        m_id(n),
        m_prompr_mtx_ptr(prompr_mtx_ptr)
{
    m_queue = std::make_shared<std::queue<std::string>>();
    m_mtx = std::make_shared<std::mutex>();
    m_stop = false;
    m_classOne_thread = std::make_shared<std::thread>(&classOne::classOne_thread_body, this);
}

void classOne::classOne_thread_body() {
    int watchDog = 0, debugDog = 0;
    m_prompr_mtx_ptr->lock();
    std::cout<<"[ Thread "<<std::to_string(m_id)<<" ] Started"<<std::endl;
    m_prompr_mtx_ptr->unlock();
    while (!m_stop) {
        m_mtx->lock();
        if (!m_queue->empty()) {
            m_prompr_mtx_ptr->lock();
            std::cout<<"[ Thread "<<std::to_string(m_id)<<" ] Received message: "<<m_queue->front()<<std::endl;
            m_prompr_mtx_ptr->unlock();
            m_queue->pop();
            watchDog = 0;
        }
        m_mtx->unlock();

        ++watchDog;
        if (watchDog>= 1000) { m_stop = true; }
        if (watchDog - debugDog > 100) {
            m_prompr_mtx_ptr->lock();
            std::cout<<"WatchDog: "<<watchDog<<std::endl;
            m_prompr_mtx_ptr->unlock();
            debugDog = watchDog;
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }
}

void f2(int n, std::vector<classOne> elements)
{
    for (int i = 0; i < 100; ++i) {
        for(std::vector<classOne>::iterator it=elements.begin(); it!=elements.end(); ++it) {
            it->m_mtx->lock();
            it->m_queue->push(std::string("Message "+std::to_string(i)+" to thread "+std::to_string(it->m_id)+" from "+std::to_string(n)));
            it->m_mtx->unlock();
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
}

int main()
{
    std::thread t1; // t1 is not a thread
    int generators = 10;
    std::vector<classOne> genClassOnes;
    std::shared_ptr<std::mutex> prompr_mtx_ptr = std::make_shared<std::mutex>();

    for (int i = 0; i < generators; i++) {
        genClassOnes.push_back(classOne(i, prompr_mtx_ptr));
    }

    std::thread t2(f2, 1, genClassOnes); // pass by value
    t2.join();

    for (std::vector<classOne>::iterator iter=genClassOnes.begin(); iter!=genClassOnes.end(); ++iter) {
        iter->m_classOne_thread->join();
    }
}

And this is the wrong output:

[ Thread 3 ] Started
[ Thread 8 ] Started
[ Thread 9 ] Started
[ Thread 9 ] Started
[ Thread 9 ] Started
[ Thread 9 ] Started
[ Thread 9 ] Started
[ Thread 9 ] Started
[ Thread 9 ] Started
[ Thread 9 ] Started
[ Thread 9 ] Received message: Message 0 to thread 9 from 1

Aucun commentaire:

Enregistrer un commentaire