Future & Promises Examples
Producer Thread Example
// The Producer's task function takes an std::promise as argument
void produce(std::promise<int>& px)
{
// Produce the result
int x = 42;
// Store the result in the shared state
px.set_value(x);
}
Consumer Thread Example
// The consumer's task function takes an std::future as argument
void consume(std::future<int>& fx)
{
// Get the result from the shared state
int x = fx.get();
}
Parent Thread Example
// Create an std::promise object
std::promise<int> prom;
// get the associated future
std::future<int> fut = prom.get_future();
// The producer task function takes the promise as argument
std::thread thr_producer(produce, std::ref(prom));
// The consumer task function takes the future as argument
std::thread thr_consumer(consume, std::ref(fut));
Producer Consumer with Exception Handling
-
In the producer thread
- Put a try block around code that might throw
- In the catch block, call
set_exception()on the promise - This captures the active exception
-
set_exception()takes a pointer to the exception object- We can use a catch-all handler
- Pass the return value from
std::current_exception()
-
In the consumer thread
- Put a try block around the call to
get()orwait() - Write a catch block to handle the exception
- Put a try block around the call to
Producer with Exception Handling
void produce(std::promise<int> &px) {
try {
// code that may throw
...
// If no exception, store the result in the shared state
px.set_value(x);
} catch (...) {
// Exception caught - store it in the shared state
px.set_exception(std::current_exception());
}
}
Consumer with Exception Handling
void consume(std::future<int> &fx) {
try {
// Get the result from the shared state - may throw
int x = fx.get();
} catch (...) {
// Exception thrown - get it from the shared state
}
}
Producer with std::make_exception_ptr()
-
To throw an exception ourselves, we could
- Throw the exception inside a try block
- Write a catch block that calls
set_exception()
-
C++11 has
std::make_exception_ptr()- Takes the exception object we want to throw
- Returns a pointer to its argument
- Pass this pointer to
set_exception() - Avoid "boilerplate" code
- Better code generation
void produce(std::promise<int> &px) {
...
if (...) {
px.set_exception(std::make_exception_ptr(std::out_of_range("Oops")));
return;
}
// Store the result in the shared state
px.set_value();
}