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() or wait()
    • Write a catch block to handle the exception

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();
}