mercredi 6 juin 2018

C++11: Publisher/Consumer pattern does not finish unless publisher sleeps

In C++, I am trying to get a handle for the publisher/consumer pattern using a condition_variable. This is loosely the template I have seen online:

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
#include <queue>
#include <condition_variable>
#include <chrono>

using namespace std;

mutex m;
queue<string> que;
condition_variable cond;

void write(string &&msg) {
    unique_lock<mutex> locker(m);
    que.push(msg);
    locker.unlock();
    cond.notify_one();
    this_thread::sleep_for(chrono::milliseconds(1));
}

void read() {
    while (true) {
        unique_lock<mutex> locker(m);
        cond.wait(locker);
        if (!que.empty()) {
            cout << que.front() << endl;
            que.pop();
        }
        locker.unlock();
    }
}

void publisher(string &msg) {
    for (int i = 0; i < 100; ++i)
        write("Publisher: " + msg + ", " + to_string(i));
}

int main() {

    string msg = "Hello";
    thread pub_thread(publisher, std::ref(msg));

    /* The main thread will print the publisher's messages to cout. */
    read();

    /* Make the main thread wait for the publisher to finish. */
    pub_thread.join(); //
    return 0;
}

The thing I do not understand is the sleep_for call on the publisher thread. I understand that this is there simply to simulate a "real life" scenario in which the publisher will not be spitting out messages so fast. However, curiously, if I comment out that line, the code does not run to completion. Why is that?

Furthermore, I tried setting the sleep_for time to 0 with the same effect. It seems that the published fundamentally needs to sleep, but I do not understand why.

Bonus points if there is a better pattern which avoids having to put the publisher to sleep...

Aucun commentaire:

Enregistrer un commentaire