Grzegorz
Grzegorz

Reputation: 3335

std::future with temporary std::promise

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?

Upvotes: 4

Views: 2011

Answers (2)

Dhwani Katagade
Dhwani Katagade

Reputation: 1240

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

Upvotes: 0

Stephan Lechner
Stephan Lechner

Reputation: 35154

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.

Upvotes: 4

Related Questions