I am trying to signal a function on a seperate thread using a std::promise
class MyClass {
std::promise<void> exitSignal;
std::thread monitorThread;
}
void MyClass::start() {
exitSignal = std::promise<void>();
std::future<void> futureObj = exitSignal.get_future();
monitorThread = std::thread(&MyClass::monitorFunction, this, std::move(futureObj));
}
void MyClass::stop() {
exitSignal.set_value();
if (monitorThread.joinable()) {
monitorThread.join();
}
}
void MyClass::monitorFunction(std::future<void> futureObj) {
while (futureObj.wait_for(std::chrono::seconds(1)) == std::future_status::timeout) {
// do stuff
}
}
It works well until I try to call start for a second time. Then I get an error
std::future_error: Promise already satisfied
How come? I refresh the promise every time I start and the future seems valid...
CodePudding user response:
I am going to echo the comment by @Homer512 and suggest that you are calling stop()
twice. I made a small test using your code:
#include <future>
#include <thread>
#include <iostream>
#include <chrono>
struct MyClass
{
std::promise<void> exitSignal;
std::thread monitorThread;
void start();
void stop();
void monitorFunction(std::future<void> futureObj);
};
void MyClass::start()
{
exitSignal = std::promise<void>();
std::future<void> futureObj = exitSignal.get_future();
monitorThread = std::thread(&MyClass::monitorFunction, this, std::move(futureObj));
}
void MyClass::stop()
{
exitSignal.set_value();
if (monitorThread.joinable())
{
monitorThread.join();
}
}
void MyClass::monitorFunction(std::future<void> futureObj)
{
while (futureObj.wait_for(std::chrono::seconds(1)) == std::future_status::timeout)
{
std::cout << "Bla\n";
}
}
int main()
{
MyClass myc;
std::cout << "Start 1\n";
myc.start();
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "Stop 1\n";
myc.stop();
// myc.stop(); // <- Boom!
std::cout << "Wait\n";
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "Start 2\n";
myc.start();
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "Stop 2\n";
myc.stop();
}
When I run this as is (second stop
commented out), it runs with no issues:
Start 1
Bla
Bla
Stop 1
Wait
Start 2
Bla
Bla
Stop 2
But if the second stop
is put in, then it is hit by an exception:
terminate called after throwing an instance of 'std::future_error'
what(): std::future_error: Promise already satisfied
Aborted