samedi 11 mars 2017

Guard protection of global stream does not seem to work

I don't understand why the code bellow using cout does not seem to work. Console output seems garbled every once in while. If I make a LOCAL console stream with Qt library (LOCAL to shared_print function), code works fine. I don't know how to make a local block scoped cout, this is why I used Qt console stream in example as proof of concept.

It is quite interesting that the cout example does not work since I would think my guarded use of cout should avoid race conditions in this particular code. I realize that if something is global, any and all use of that global must be guarded... so one would think in this example where all use of it is guarded would work, but alas no...

#include <QCoreApplication>
#include <iostream>
#include <QTextStream>
#include <thread>                       //C++11 Threading
#include <mutex>                        //Using to get sane console output by avoiding race condition
#include <chrono>                       //Using for timer
#include <sstream>                      //Used to convert thread::id to string

using namespace std;

void shared_print(string s, thread::id id = thread::id(777))
{
    mutex m;
    lock_guard<mutex> guard(m);
    //QTextStream out(stdout);          //WORKS but std::cout doesn't
    stringstream ss;

    ss << id;

    // WORKS
    //if(id != thread::id(777))
    //  out <<  QString::fromStdString(s) << QString::fromStdString(ss.str()) << endl;
    //else
    //  out << QString::fromStdString(s) << endl;

    //DOES NOT WROK
    if(id != thread::id(777))
        cout <<  s << ss.str() << endl;
    else
       cout << s << endl;
}

void func1(int x){
    for(int i = 0; i < 20; i++){
         shared_print("FromThread:" + to_string(x) + " Function:func1" + " ID:" , std::this_thread::get_id() );
    }

}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    vector<thread> workers;
    unsigned int numWorkers = std::thread::hardware_concurrency();
    for (unsigned int i = 1; i <= numWorkers; i++) {
        workers.push_back( thread(func1, i) );
    }

//    shared_print("FromMainThread pre join() :: No. of threads C++ recomends: " +  to_string(std::thread::hardware_concurrency()) );
//    shared_print("FromMainThread pre join() :: ID of main Thread   = " , std::this_thread::get_id() );


    for (auto& worker : workers) {          
        if(worker.joinable())               
            worker.join();
    }

    shared_print("main thread post join()");     


    return a.exec();
}

Aucun commentaire:

Enregistrer un commentaire