Promise and Future

Contents[Show]

With std::promise and std::future, you have the full control over the task.

Full control over the task

A std::promise permits

  • to set a value, a notification or an exception. That result can in addition delayed be provided by the promise.

A std::future permits to

  • pick up the value from the promise.
  • asks the promise, if the value is available.
  • wait for the notification of the promise. That waiting can be done with a relative time duration or an absolute time point. => Replacement for condition variables.
  • create a shared future (std::shared_future).

 

Both communication endpoints promise and future can be moved in a separate thread. So the communication is taking place between threads.

 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
// promiseFuture.cpp

#include <future>
#include <iostream>
#include <thread>
#include <utility>

void product(std::promise<int>&& intPromise, int a, int b){
  intPromise.set_value(a*b);
}

struct Div{

  void operator() (std::promise<int>&& intPromise, int a, int b) const {
    intPromise.set_value(a/b);
  }

};

int main(){

  int a= 20;
  int b= 10;

  std::cout << std::endl;

  // define the promises
  std::promise<int> prodPromise;
  std::promise<int> divPromise;

  // get the futures
  std::future<int> prodResult= prodPromise.get_future();
  std::future<int> divResult= divPromise.get_future();

  // calculate the result in a separat thread
  std::thread prodThread(product,std::move(prodPromise),a,b);
  Div div;
  std::thread divThread(div,std::move(divPromise),a,b);

  // get the result
  std::cout << "20*10= " << prodResult.get() << std::endl;
  std::cout << "20/10= " << divResult.get() << std::endl;

  prodThread.join();
  
  divThread.join();

  std::cout << std::endl;

}

 

The thread prodThread (line 36) uses the function product (line 8 -10), the prodPromise (line 32) and the numbers a and b. To understand the arguments of the thread prodThread, you have to look at the signature of the function. prodThread needs as first argument a callable. This is the already mentioned function product. product needs a promise of the kind rvalue reference (std::promise<int>&& intPromise) and two numbers. These are exactly the last three arguments of the thread prodThread. std::move in line 36 creates the rvalue reference. The rest is a piece of cake. The thread divThread (line38) divides the two numbers a and b. For is job, it uses the instances div of the class Div (line 12 - 18). div is a function object.

The futures picks up the results by the calls prodResult.get() and divResult.get()

promiseFuture

Per default, there is a one-to-one relation between the promise and the future. But std::shared_future supports a one-to-many relations between a promise and many futures.

std::shared_future

A std::shared_future 

  • permits you to ask the promise independent of the other associated futures.
  • has the same interface as a std::future.
  • can be created by a std::future fut with the call fut.share().
  • can be created by a std::promise divPromise with the call std::shared_future<int> divResult= divPromise.get_future().

The managing of std::shared_future is special.

 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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// sharedFuture.cpp

#include <exception>
#include <future>
#include <iostream>
#include <thread>
#include <utility>

std::mutex coutMutex;

struct Div{

  void operator()(std::promise<int>&& intPromise, int a, int b){
    try{
      if ( b==0 ) throw std::runtime_error("illegal division by zero");
      intPromise.set_value(a/b);
    }
    catch (...){
      intPromise.set_exception(std::current_exception());
    }
  }

};

struct Requestor{

  void operator ()(std::shared_future<int> shaFut){

    // lock std::cout
    std::lock_guard<std::mutex> coutGuard(coutMutex);

    // get the thread id
    std::cout << "threadId(" << std::this_thread::get_id() << "): " ;

    // get the result
    try{
      std::cout << "20/10= " << shaFut.get() << std::endl;
    }
    catch (std::runtime_error& e){
      std::cout << e.what() << std::endl;
    }
  }

};

int main(){

  std::cout << std::endl;

  // define the promises
  std::promise<int> divPromise;

  // get the futures
  std::shared_future<int> divResult= divPromise.get_future();

  // calculate the result in a separat thread
  Div div;
  std::thread divThread(div,std::move(divPromise),20,10);

  Requestor req;
  std::thread sharedThread1(req,divResult);
  std::thread sharedThread2(req,divResult);
  std::thread sharedThread3(req,divResult);
  std::thread sharedThread4(req,divResult);
  std::thread sharedThread5(req,divResult);

  divThread.join();

  sharedThread1.join();
  sharedThread2.join();
  sharedThread3.join();
  sharedThread4.join();
  sharedThread5.join();

  std::cout << std::endl;

}

 

Both work packages of the promise and the future are in this current example function objects. In case you divide to numbers, you have to take care of the denominator. It must not be 0. If is is 0, you get an exception. The promise deals with this issue by catching the exception (line 18 - 20) and rethrowing it to the future. The std::future catches the exception and displays it in line 40. In line 58, divPromise will be moved and executed in divThread. Accordingly, the std::shared_future's are copied in the five threads. I will emphasis this once more. In opposite to a std::future object, which can only be moved, you can copy a std::shared_future object.

The main thread waits In the line 69 to 73 for its child´s and shows the results.

sharedFuture

What's next?

There is one oddity with std::async, which you should know. The by std::async created future blocks in its destructor until the associated promise is done. Curious? Read the next post.

 

 

 

 

 

 

title page smalltitle page small Go to Leanpub/cpplibrary "What every professional C++ programmer should know about the C++ standard library".   Get your e-book. Support my blog.

 

 

 

Tags: tasks

Comments   

0 #1 Mandila Jackson 2016-10-09 11:02
Thаnks a ton! It a amazing site!
Quote
0 #2 Coletta 2016-10-15 03:33
You have got astonishing stuff right here.
Quote
0 #3 وظائف خالية في مصر 2016-11-22 07:30
Remarkable issues here. I'm very satisfied to peer your post.

Thanks so much and I'm looking ahead to touch you. Will you kindly drop me a mail?
Quote

Add comment


My Newest E-Books

Latest comments

Subscribe to the newsletter (+ pdf bundle)

Blog archive

Source Code

Visitors

Today 599

All 455653

Currently are 160 guests and no members online