Подтвердить что ты не робот

Уведомление о переменной состояния С++ не работает должным образом

Я пытаюсь запустить новые потоки, как только работа в предыдущем worker_thread началась , но может закончиться или нет. Я заменил начатое и закончил работу с временными задержками. Мой код:

#include <iostream>
#include <string>
#include <mutex>
#include <condition_variable>
#include <future>
#include <atomic>
#include <chrono>
#include <thread>

std::mutex m;
std::condition_variable cv;
bool started = false;

void worker_thread()
{
    std::unique_lock<std::mutex> lk(m);

    static std::atomic<int> count(1);
    std::this_thread::sleep_for(std::chrono::milliseconds{(count % 5) * 100});
    std::cerr << "Start Worker thread: " << count << "\n";

    started = true;
    lk.unlock();
    cv.notify_one();

    std::this_thread::sleep_for(std::chrono::milliseconds{3000});
    std::cerr << "Exit Worker thread: " << count << "\n";
    ++count;
}

int main()
{
    while(1) {
        std::async(std::launch::async, worker_thread);
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return started;});
        started = false;
    }
}

Результат выглядит следующим образом:

Start Worker thread: 1
Exit Worker thread: 1
Start Worker thread: 2
Exit Worker thread: 2
Start Worker thread: 3
Exit Worker thread: 3
Start Worker thread: 4
Exit Worker thread: 4
Start Worker thread: 5
Exit Worker thread: 5

который не является поведением, которое я хотел. То, что я хотел, было чем-то вроде (не совсем):

Start Worker thread: 1
Start Worker thread: 2
Start Worker thread: 3
Start Worker thread: 4
Exit Worker thread: 1
Exit Worker thread: 3
Exit Worker thread: 4
Exit Worker thread: 2
Start Worker thread: 5
Exit Worker thread: 5

В настоящее время следующий поток запускается только при завершении работы в предыдущем потоке. Но я хочу начать следующий поток, как только работа начнется в предыдущем потоке, и не дожидаться конца, только дождитесь запуска.

4b9b3361

Ответ 1

std::async возвращает std::future результат выполнения функции. В вашем случае это временный объект, который уничтожен. В документации для std::future говорится:

эти действия не будут блокировать для состояния общего состояния, чтобы быть готовым, за исключением того, что он может блокироваться, если все следующие являются истинными:

✔ общее состояние было создано вызовом std:: async

✔ общее состояние еще не готово

✔ Это была последняя ссылка на общее состояние

Все они верны, поэтому уничтожение этого future будет блокироваться до завершения выполнения рабочей функции.

Вы можете создать отдельный поток, чтобы избежать этой проблемы:

std::thread(worker_thread).detach();