Is it ok to destroy a std::promise before future.get() is called?
Asked Answered
C

1

21

I was wondering if it is ok to call promise.get_future(), move that future somewhere else (e.g. into a vector) and possibly let the promise die before even the future.get() is called. In the following example, the call gateway->refreshWithCallback executes the lambda in a thread so that the shared pointer may set the promise free even if in the second loop the future.get() was not called yet, which seems to work but I am angsty!

std::vector<std::future<bool>> futures;
for(GuiGateway *gateway : gateways){
    std::shared_ptr<std::promise<bool>> shared_promise_ptr(new std::promise<bool>());
    futures.push_back(shared_promise_ptr.get()->get_future());
    gateway->refreshWithCallback([shared_promise_ptr](bool success){
        shared_promise_ptr.get()->set_value(success);
    });
}

qDebug() << "waiting for futures";

for(std::future<bool> &future : futures){
    if(future.get() == false){
        qDebug() << "error retrieving all gateway data, aborting auto config";
        return;
    }
}
Cleric answered 23/1, 2018 at 18:16 Comment(2)
Note that there exists std::make_shared which may be a bit more efficient at creating new objects that will be stored in a std::shared_ptr (allocates enough memory for the object and the control block in one shot) and covers an edge case regarding exception safety. It also saves on repetition, you can write auto shared_promise_ptr = std::make_shared<std::promise<bool>>();.Antibody
I would up-vote this question if it was a little more succinct. The example is unnecessarily specific (and thus verbose), You could make it simpler and more general.Separatist
S
46

If you provide a value to the std::promise before destroying it, the associated std::future will be able to retrieve it just fine. It does not depend on std::promise still existing. If you failed to provide a value to std::promise before destroying it, trying to get a result from the std::future will throw std::future_error but it is also well defined.

Steelyard answered 23/1, 2018 at 18:22 Comment(3)
I love this answer. It wipes away a hole in my understanding. To be more concrete: in a (potential) asynchronous function I can use a local promise to bail out in a synchronous error path. Not caring (yet) about the promise a asynchronous-call will make later on.Folium
If providing a value is fine, is setting an exception fine as well? I’d assume yes, because all it comes to is if the shared state exists after ~std::promise runs.Hectogram
@Hectogram Providing an exception instead of a value follows the same reasoning and will work following the same rules.Antibody

© 2022 - 2024 — McMap. All rights reserved.