4

I have a problem with understanding how the promise cooperates with future. I have a function that is returning std::future like in this example:

std::future<int> calcSomeValue() { } 

My problem is that this future can be either calculated asynchronously spawning a thread, or can have a result already ready to return, so I would like to have it returned using std::promise without running a thread. But... I don't know if this is safe or not or what else could I do. See example:

std::future<int> calcSomeValue() { if (resultIsReady()) { std::promise<int> promise; // on the stack std::future<int> rv = promise.get_future(); // is future part of the memory occupied by promise? promise.set_value(resultThatIsReady); // does it store the value in promise or in future? return rv; // <--- What will happen when promise is lost? } else { return std::async(....) } } 

See the comment in the code above. Is future accessing promise variable when .get() is called, where promise is already fulfilled? If it is then I will have a big doo doo here.

Can anyone advise me how can I return std::future in this particular case?

3
  • 2
    Once the promise's value is set, the shared state object shared between the promise and the future is also set. The promise doesn't have to survive after being set. The std::promise is the mail slot where you push the response through, it doesn't store the response. Commented Jul 9, 2018 at 19:16
  • 1
    This design seems odd to me. If you are checking that a result is already ready, it implies an external worker might be calculating the result right now. If that's the case, you start another worker to do that calculation. Commented Jul 9, 2018 at 19:17
  • @FrançoisAndrieux. Merci! Do you happen to have any reference to doc that says it is safe to abandon promise? Is it possible that this may be depended on implementation? As per the oddness, we are dealing with a very rare (once a day) calculation (of course it looks differently than this one) and a single threaded, however context switching environment. Since we have to return result (taken from a calculated set of results) as fast as possible, we do not now want to spawn threads each time we request the value. Commented Jul 9, 2018 at 19:37

2 Answers 2

4

A promise-object is associated with a shared state (note the "shared"). When calling promise::get_future, you'll receive a future- object associated with the same shared state as the one with which the respective promise object is associated. This state will live at least as long as one associated producer (i.e. the promise) or a consumer (i.e. the future) lives. Hence, it does not matter if the promise's lifetime ends before the corresponding future-object.

Not normative, but see, for example, promise as described at cplusplus.com:

The lifetime of the shared state lasts at least until the last object with which it is associated releases it or is destroyed. Therefore it can survive the promise object that obtained it in the first place if associated also to a future.

Sign up to request clarification or add additional context in comments.

Comments

0

To clarify the OP's dilemma that - Is it safe to call get on the future when the promise that set the value has been deallocated? - it's important to understand the concept of the Shared State. This is explained by Scott Meyers in the book Effective Modern C++ under Item 38.

... a future is one end of a communications channel through which a callee transmits a result to a caller. The callee (usually running asynchronously) writes the result of its computation into the communications channel (typically via a std::promise object), and the caller reads that result using a future. ... the callee’s result, is stored in ... the shared state. The shared state is typically represented by a heap-based object, but its type, interface, and implementation are not specified by the Standard. Standard Library authors are free to implement shared states in any way they like.

A diagram from the book.

 Shared State +----------+ std::future +-----------+ std::promise +--------+ | Caller |<----------------+ Callee's |<---------------------+ Callee | +----------+ | Result | (typically) +--------+ +-----------+ 

Here are a few bullets to point out important concepts to catch.

  • A callee is an asynchronous function that the caller thread invokes
  • Promise and future are ends of a communication channel between caller and callee
  • The promise is a writer for the shared state while the future is a reader
  • The result generated by the callee cannot be stored in the callee because the callee’s scope may be lost by the time the caller tries to retrieve it
  • The result generated by the callee cannot be stored in the caller because the caller’s future can be copied as shared_futures but result may not be copyable
  • A separate shared state entity is needed to provide an unambiguous unique stable storage location across copies
  • The shared state is implemented in a platform dependent way usually on the heap
  • It typically uses reference counting to track futures and the promise referring to it
  • It is cleaned up when no futures or promise are referring to it
  • It is cleaned up by the thread that releases the last reference

You can read further details in the Shared State Standard Specification

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.