shared future with single promise

I am trying to understand the code below, which has three future threads running, but only a single promise, which passes the argument 4.

So the question is, how is factorial executed with three threads ?
Is it simply whichever thread finishes first returns the result?
How are three threads working with the same factorial function?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <string>
#include <future>
#include <iostream>

using namespace std;

int factorial (std::shared_future<int> f) {
  int res = 1;
  int N = f.get();

  for (int i=N; i>1; i--)
    res *= i;
    
  return res;
}

// If you have more than one future thread, then you would naturally need more than one promise,
// one for each future. This is rather clumsy though, since it is a lot of unnecessary coding.

// Solution is to have a shared_future, which will enable a shared get() function call.

int main() {
  int x {0};
  
  std::promise<int> p;
  
  // a separate future object is required due to the fact that a promise is made,
  // which is fulfilled some time in the future.
  std::future<int> f = p.get_future();
  std::shared_future<int> sf = f.share();

  // so the main thread promises to send the initial value for the factorial to the child thread
  
  // so the future promise must be passed as a reference argument to the factorial function
  std::future<int> fu = std::async(std::launch::async, factorial, sf);
  std::future<int> fu2 = std::async(std::launch::async, factorial, sf);
  std::future<int> fu3 = std::async(std::launch::async, factorial, sf);
  
  // so the the f.get(); in the factorial function waits until the promise is fulfilled.
  // do something 
  std::this_thread::sleep_for(std::chrono::milliseconds(20));

  // and now the main thread fulfils its promise
  p.set_value(4); 
  
  x = fu.get();

 
  // If the promise is not fulfilled, then an exception is raised,
  // An explicit exception can be passed to the future promise
  // p.set_exception(std::make_exception_ptr(std::runtime_error("Explicit Exception")));


  // Note !!!! Neither promise or future can be copied, they can only be moved
  cout << x;
  return 0;

}

That looks like a poor example. Each thread gets the same input (4). Each thread computes, but only the result of one (fu) is later used. The point of example is apparently that you can make copies of shared_future.
Each of the threads gets its own copy of the std::shared_future<int> object (It is passed by value)
Unlike std::future<>, shared futures are copy assignable; all copies of the same shared future refer to the same common shared state.

Howard Hinnant on stackoverflow:
In the beginning there was unique_future and shared_future and there was much discussion as to which one should be the "default". And whichever should be the default, that one should be named "future". At the time this decision was being made, move semantics was still very new to the C++ committee, and not that well understood. I credit the C++ committee with a wise leap of faith in assigning the simpler name of "future" to "unique_future"

https://stackoverflow.com/questions/16005655/what-is-the-difference-between-future-and-shared-future

thanks.
the discussion by Howward on the link you provided makes sense.
Topic archived. No new replies allowed.