Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ what are std::shared_future and std::promise

Tags:

c++

c++11

future

I understand what's std::future but i don't understand when and HOW to use std::shared_future and std::promise, and i couldn't find a good explanation online.

I will appreciate some help wrapping my head around it.

By the way the example here isn't really clear http://en.cppreference.com/w/cpp/thread/shared_future

like image 931
darkThoughts Avatar asked Jul 27 '17 19:07

darkThoughts


1 Answers

std::shared_future is when you need to have multiple valid copies of a std::future, and possibly multiple consumers of said std::future.

You can move a std::future into a std::shared_future.

Consider std::future:std::shared_future to be like std::unique_ptr:std::shared_ptr.


std::promise is one way to generate a std::future.

template<class T>
std::future<std::decay_t<T>> make_ready_future( T&& t ) {
  std::promise<std::decay_t<T>> pr;
  auto r = pr.get_future();
  pr.set_value(std::forward<T>(t));
  return r;
}

this is a toy example of std::promise, where I take a T and I generate an already-ready std::future<T> from it.

If you have code that could require threading off, or might already be calculated, you can return a std::future<T> from it. If it isn't calculated, you return the result of a std::async( ... ) call. If it is already calculated, you return a make_ready_future( calculated value ).

A slightly more complex situation:

template<class T>
struct promise_pipe {
  std::future<T> out;
  std::function<void(T)> in;
  promise_pipe() {
    auto pr = std::make_shared<std::promise<T>>();
    out = pr->get_future();
    in = [pr](T t)mutable{
      if (pr) pr->set_value(std::forward<T>(t));
      pr = {};
    };
  }
};

Here I have written a promise_pipe.

A promise_pipe<int> has two fields -- a std::future<int> out and a std::function<void(int)> in.

The out future will be ready if and only if you call in with an int.

So you can have a function that returns a std::future<Bitmap>. You have some network code that is expecting the bitmap to be streamed. So you create a promise_pipe<Bitmap>, return the std::future<Bitmap> and store the in in a "todo" list when the bitmap arrives.

When the bitmap has fully arrived, you just do in(Bitmap) and whomever is waiting on that future will be notified.


promises are objects designed to allow programmers to generate their own futures, not just use ones created by the std library.

Now a packaged_task is often easier to work with than a std::promise, and serves much the same purpose as the promise_pipe above. It is move-only, so you can end up having to wrap it into a std::shared_ptr and a std::function anyhow (or a custom move-only std::function)

like image 92
Yakk - Adam Nevraumont Avatar answered Sep 23 '22 22:09

Yakk - Adam Nevraumont