Home > Net >  use promise multiple times
use promise multiple times

Time:11-21

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
  • Related