Home > Net >  Lifetime of std::promise and std::future
Lifetime of std::promise and std::future

Time:11-09

My code:

void job_function(std::promise<void>& p) {
  do_it();
  p.set_value();
}

void foo() {

  std::promise<void> p;
  auto* thread = new std::thread(job_function, p);

  p.get_future().wait_for(std::chrono::seconds(1));

}

In this code, if the calling thread of foo only waits for 1 second until the future completes. It is quite possible that the actual job gets completed after the wait is over. In this scenario, p is destructed already so call to p.set_value will not work. I can create p on heap, but even in that case it should be deleted and which thread should delete p depends on order of job completion and wait_for. Is there a specific pattern that can be used to handle this?

CodePudding user response:

The trick is to move the promise into the thread and only keep the future around. Also, if you don't want to wait for the thread, detach it.

void job_function(std::promise<void> p) {
  do_it();
  p.set_value();
}

void foo() {
  std::promise<void> p;
  std::future<void> f = p.get_future();
  std::thread thread(job_function, std::move(p));
  thread.detach();
  f.wait_for(std::chrono::seconds(1));
}

CodePudding user response:

You are reimplementing std::packaged_task. Your code could be:

void job_function() {
  do_it();
}

void foo() {
  std::packaged_task<void(void)> task(job_function);
  std::future result = task.get_future();
  std::thread task_td(std::move(task));
  result.wait_for(std::chrono::seconds(1));
}

CodePudding user response:

shared_ptr to the rescue

void job_function(std::shared_ptr<std::promise> p) {
  do_it();
  p->set_value();
}

void foo() {

  std::shared_ptr<std::promise> spPromise = std::make_shared<std::promise>();    
  
  auto* thread = new std::thread(job_function, spPromise);

  spPromise->get_future().wait_for(std::chrono::seconds(1));
}

Now it doesn't matter if the thread completes before or after the original function that waits returns. The promise objects gets deleted when the last instance of the shared_ptr goes away.

If you want to keep the pass by reference semantics, just keep the shared_ptr captured by value for the lifetime of the thread.

void job_function(std::promise>& p) {
  do_it();
  p.set_value();
}

void foo() {

  std::shared_ptr<std::promise> spPromise = std::make_shared<std::promise>();    

  std::promise& p = *spPromise.get();

  auto* thread = new std::thread([spPromise] {
      job_function(*spPromise.get());  // same as job_function(p)
  });

  p.get_future().wait_for(std::chrono::seconds(1));
}
  •  Tags:  
  • c
  • Related