The following program still interleaves the output to std::cout
. I tried to add a std::mutex
to control access to std::cout
via std::lock_guard
, but it still interleaves.
#include <iostream>
#include <chrono>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>
std::mutex global_mtx{};
class Timer {
public:
Timer(size_t time, const std::function<void(void)>& f) : time{std::chrono::milliseconds{time}}, f{f} {}
~Timer() { wait_thread.join(); }
private:
void wait_then_call()
{
std::unique_lock<std::mutex> lck{mtx};
for(int i{10}; i > 0; --i) {
{
std::lock_guard<std::mutex>{global_mtx};
std::cout << "Thread " << wait_thread.get_id() << " countdown at: " << '\t' << i << std::endl;
}
cv.wait_for(lck, time / 10);
}
f();
}
std::mutex mtx;
std::condition_variable cv{};
std::chrono::milliseconds time;
std::function <void(void)> f;
std::thread wait_thread{[this]() {wait_then_call(); }};
};
int main()
{
auto f = []() {std::lock_guard<std::mutex>{global_mtx}; std::cout << "---------------- I waited to print! ----------------" << std::endl; };
Timer t1{3'000,f};
Timer t2{6'000,f};
Timer t3{2'000,f};
Timer t4{1'000,f};
}
Do I need to control access through a separate class or dedicated thread?
Your problem is here:
std::lock_guard<std::mutex>{global_mtx};
creates a lock guard and immediately releases it. You need to create a variable to hold the lock, likestd::lock_guard<std::mutex> lock{global_mtx};
.