I'm trying to implement a basic timer with the classic methods: start() and stop(). I'm using c++11 with std::thread and std::chrono.
I created and started a Timer object that show "Hello!" every second, then with other thread I try to stop the timer but I can't. The Timer never stops.
I think the problem is with th.join()[*] that stops execution until the thread has finished, but when I remove th.join() line obviously the program finishes before the timer start to count.
So, my question is how to run a thread without stop other threads?
#include <iostream>
#include <thread>
#include <chrono>
using namespace std;
class Timer
{
thread th;
bool running = false;
public:
typedef std::chrono::milliseconds Interval;
typedef std::function<void(void)> Timeout;
void start(const Interval &interval,
const Timeout &timeout)
{
running = true;
th = thread([=]()
{
while (running == true) {
this_thread::sleep_for(interval);
timeout();
}
});
// [*]
th.join();
}
void stop()
{
running = false;
}
};
int main(void)
{
Timer tHello;
tHello.start(chrono::milliseconds(1000),
[]()
{
cout << "Hello!" << endl;
});
thread th([&]()
{
this_thread::sleep_for(chrono::seconds(2));
tHello.stop();
});
th.join();
return 0;
}
Output:
Hello!
Hello!
...
...
...
Hello!
In Timer::start
, you create a new thread in th
and then immediately join
it with th.join()
. Effectively, start
won't return until that spawned thread exits. Of course, it won't ever exit because nothing will set running to false until after start
returns...
Don't join
a thread until you intend to wait for it to finish. In this case, in stop
after setting running = false
is probably the correct place.
Also - although it's not incorrect - there's no need to make another thread in main
to call this_thread::sleep_for
. You can simply do so with the main thread:
int main()
{
Timer tHello;
tHello.start(chrono::milliseconds(1000), []{
cout << "Hello!" << endl;
});
this_thread::sleep_for(chrono::seconds(2));
tHello.stop();
}
Instead of placing the join
in start
place it after running = false
in stop
. Then the stop method will effectively wait until the thread is completed before returning.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With