В C ++ я пытаюсь получить дескриптор для шаблона издатель / потребитель, используя condition_variable
.Это в общих чертах шаблон, который я видел в Интернете:
#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;
}
Я не понимаю, что такое вызов sleep_for
в ветке издателя.Я понимаю, что это просто для имитации сценария "реальной жизни", при котором издатель не будет так быстро выплевывать сообщения.Однако, как ни странно, если я закомментирую эту строку, код не будет завершен.Это почему?
Кроме того, я попытался установить время сна для 0 равным 0 с тем же эффектом.Кажется, что опубликованным принципиально нужно спать, но я не понимаю почему.Чтобы получить более конкретный код должен распечатать 100 сообщений.Если я оставлю код в спящем режиме на 1 мс, то будут напечатаны все 100 сообщений.Если нет, то я вижу только около 10 сообщений, прежде чем код зависнет.Кажется, что возникла тупиковая ситуация.
Бонусные баллы, если существует лучший шаблон, позволяющий избежать необходимости усыплять издателя ...
Я знаю, что на практике вам нужна стратегия остановки основного потока,как таблетка с ядом.Я намеренно пропустил это, чтобы сосредоточиться на настоящем обсуждении.
РЕДАКТИРОВАТЬ
Хммм.Если я вставлю блок для обработки ложного пробуждения, то это решит проблему.Но это все еще не объясняет, почему оригинальный код не удался.
Вот улучшенная функция чтения:
void read() {
while (true) {
unique_lock<mutex> locker(m);
cond.wait(locker, [&](){ return !que.empty(); });
cout << que.front() << endl;
que.pop();
locker.unlock();
}
}