Detail understanding and usage of std::async in C++ 11

Detail understanding and usage of std::async in C++ 11

Agenda:

  • Introduction to std::async.
  • Accessing the shared state of the future.
  • Get a value from parent to child- Full filling promise.
  • set_exception – failed to full fill promise and sets an exception instead:

Introduction to std::async:

std::async call function asynchronously,

  • Invokes function fn at some point, returning without waiting for the execution of fn to complete
  • The value returned by fn can be accessed through the future object.
policydescription
launch::asyncAsync: Launches a new thread to call function fn
launch::deferredDeferred: The call to function fn is deferred until the shared state of the returned future is accessed (with wait or get).
launch::async|launch::deferredAutomatic:  This depends on the system and library implementation, which generally optimizes for the current availability of concurrency in the system.

1. Accessing the shared state of the future:

To access share state of future use API get() as shown in below example.

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

using namespace std;

int work()
{
    this_thread::sleep_for(chrono::milliseconds(5000));
    return 10;
}

int main()
{
    future fr = async(launch::async, work);
    cout << "Parent waiting to get a value from child" << endl;
    int val = fr.get();

    std::cout << "Return value from child : " << val << endl;
    return 0;
}

Output:

Parent waiting to get a value from child
Return value from child: 10

2. Get a value from parent to child- Full filling promise:

The parent passes future object and promise to set value. In below example,

  • The function ‘main’ passes the future object to function ‘work’.
  • The function ‘work’ waits by invoking API get().
  • The parent function fulfills the promise by invoking an API set_value().
int work(future &fu)
{
    cout << "waiting to fulfill promise" << endl;
    fu.get();
    
    cout << "Promise full filled" << endl;
    return 10;
}

int main()
{
    promise p;
    future fu = p.get_future();
    future<int> fr = async(launch::async, work, ref(fu));

    this_thread::sleep_for(chrono::milliseconds(5000));
    p.set_value(10.2);

    cout << "Parent waiting to get a value from child" << endl;
    int val = fr.get();


    std::cout << "Return value from child : " << val << endl;
    return 0;
}

Output:

waiting to fulfill promise
Parent waiting to get a value from child
Promise full filled
Return value from child: 10

3. set_exception – failed to full fill promise and sets an exception instead:

When the parent failed to full fill the promise API set_exception() can be used to set an exception mainly to avoid the infinite wait.

int work(future &fu)
{
    try
    {
        cout << "waiting to fulfill promise" << endl;
        fu.get();
        cout << "Promise full filled" << endl;
    }
    catch (exception &ex)
    {
        cerr << ex.what() << endl;
    }
    return 10;
}

int main()
{
    promise p;
    future fu = p.get_future();
    future<int> fr = async(launch::async, work, ref(fu));

    this_thread::sleep_for(chrono::milliseconds(5000));
    //p.set_value(10.2);
    p.set_exception(make_exception_ptr(runtime_error("Failed to fullfill promise")));

    cout << "Parent waiting to get a value from child" << endl;

    int val = fr.get();
    std::cout << "Return value from child : " << val << endl;
    return 0;
}

Output:

waiting to fulfill promise
Parent waiting to get a value from child
Failed to fullfill promise
Return value from child : 10