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));
}