14
votes

I have a function that returns a reference to a std::promise:

std::shared_ptr<std::promise<void>> play();

(More info: The function plays media on some device, and the return value represents when this playing is complete. If play is called a second time, a value is set on the promise returned the first time, and a new promise is created and returned for this second call)

The caller can then catch the value and wait on the future:

auto this_future = play()->get_future();
this_future.wait();

Does it make sense to return a reference to the promise, or should I return the future instead, so that the calling function does not have to call get_future()?

1
Having a std::promise/std::future in a std::shared_ptr might be questionable (It breaks the no copy concept of std::promise/std::future)user2249683
Agreed; the shared_ptr was actually needed to get around these no-copy issues, as I wanted to store them in a collection and return them from a function. However, I can't see where this would cause issues.Scott M
@ScottM: You can also std::move futures if you want to store then in a collection, say std::vector<std::future<T>>.Nawaz
You read my mind! I've been sitting here trying to figure out if I could modify the second function playAll() to return std::vector<std::future<void>> instead of the corresponding collection of promise refereneces.Scott M
The no-copy premise of std::future means that only ONE consumer should ever have it and think they have the right to .get() from it. With a std::shared_ptr<std::future<X>>, you are saying "more than one client has equal ownership of this future". This is code smell. Similarly, std::promise<X> is supposed to be uniquely owned by the producer of the data: having two pieces of code with shared ownership implies both have the right to set its value (or read its future). play() should return std::future<void>. Internally a std::promise<void> old_promise can be kept around.Yakk - Adam Nevraumont

1 Answers

13
votes

Since the implementation of play() is not posted, I'd say most likely you should return the future, and the function should work with the promise itself, most likely in a different thread. The rationale for this design stems from the fact that promise is a producer end, and future is a consumer end — so the function would produce a value, set it through the promise instance, which will notify the future that result has arrived through get.

However, note that, you don't have to return a std::shared_ptr<std::future<T>> — just std::future<T> would work great.