У меня есть один поток, который толкает в очередь и тот, который потребляет элементы из очереди. Обработка одного из элементов асинхронна, но я не хочу обрабатывать другие элементы во время обработки. (Предположим, что выходной поток и очередь потокобезопасны)
Интересно, что лучший способ реализовать поток потребления ... Я думаю, что пока (правда) и условия не лучший выбор.
Простая реализация (process2 должна быть синхронной).
#include <iostream>
#include <queue>
#include <thread>
#include <atomic>
#include <future>
std::atomic_bool isProcess2Processing{false};
void process0()
{
std::cout << "process0" << std::endl;
}
void process1()
{
std::cout << "process1" << std::endl;
}
void process2()
{
std::async(std::launch::async, []() { isProcess2Processing = true; std::cout << "start process2" << std::endl; while (std::rand() > 10000) {}; std::cout << "finished proces2" << std::endl; isProcess2Processing = false; });
}
void consume(int x)
{
if (x == 0)
{
process0();
}
else if (x == 1)
{
process1();
}
else
{
process2();
}
}
int main()
{
std::queue<int> q;
std::thread consumingThread([&q]() {
while (true) {
if (!q.empty() && !isProcess2Processing) {
consume(q.front());
q.pop();
}
}
});
while (true)
{
q.push(std::rand() % 3);
}
}
Ваше созерцание здесь оправдано: самая большая проблема с использованием такого цикла while (т. е. без какого-либо ожидания) заключается в том, что вы теряете время и мощность процессора. Ваш вторичный поток (и для кода, предоставленного вашему основному потоку) также сохраняет ядро процессора в течение некоторого времени без видимых причин, так что другие задачи не могут получить процессорное время для себя.
Самый наивный путь к изменению, который добавляет какой-то sleep, как здесь:
std::thread consumingThread([&q]() {
while (true) {
if (!q.empty() && !isProcess2Processing) {
consume(q.front());
q.pop();
}
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
});
Здесь вы будете спать в течение 5 мс, в течение которого планировщик сможет позволить другим задачам выполнять свою работу.
Несколько вещей, кроме того, вы должны убедиться, что для каждого цикла есть условие выхода, а также вызывать consumingThread.join();, прежде чем покинуть main().