Home C++ Decisions Loops Input/Output Functions Stack and Heap References Arrays Searching and Sorting Recursion Pointers Character and Strings Structures Classes Inheritance Exceptions Templatess STL Modern C++ Misc Books ----

Threads


Contents

Async

Sometimes we need to execute a function but we do not want to wait for the function to return. Instead we want to proceed with the code and obtain the result of the function at a later time. This can be done with the "std::async" call.

File: async1.cpp
#include <iostream>
#include <future>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>

using namespace std ;

int calculate_value()
{
    cout << "Calculating value in background...\n";
    this_thread::sleep_for(chrono::seconds(20)); // Simulate long computation
    return 42;
}

int main()
{
    future<int> future_result = async(launch::async, calculate_value);

    cout << "Main thread continues to execute...\n";

    cout << "Waiting for result...\n";
    int result = future_result.get(); // Blocks until the result is available

    cout << "Result is: " << result << endl;

    return 0;
}

$ ./a.exe
Main thread continues to execute...
Calculating value in background...
Waiting for result...
Result is: 42

We use the call:
  future future_result = async(launch::async, calculate_value);

to start the worker thread. This returns a future object. We specify the type
that the function "calculate_value" returns in the "future" class. The
"async" call returns immediately. A new thread is created and the
function "calculate_value" starts executing in the new thread.

We then use the "get()" call on the future object.

int result = future_result.get();

This call will block till the "calculate_value" finishes.
Once the result is obtained, the worker thread exits and
the main thread prints the result.

We now study the option "launch::deferred" instead of
"launch::async" .

With deferred we don't call the function in a separate thread
but call it in the same thread when "get" or "wait" is called.


File: async1a.cpp
#include <iostream>
#include <future>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>

using namespace std ;

int calculate_value()
{
    cout << "Calculating value in background...\n";
    this_thread::sleep_for(chrono::seconds(20)); // Simulate long computation
    return 42;
}

int main()
{
    future<int> future_result = async(launch::deferred, calculate_value);

    cout << "Main thread continues to execute. Waits for 10 seconds\n";
    this_thread::sleep_for(chrono::seconds(10));
    cout << "Waiting for result...\n";
    int result = future_result.get(); // Blocks until the result is available

    cout << "Result is: " << result << endl;

    return 0;
}
$ g++ async1a.cpp ; ./a.exe
Main thread continues to execute. Waits for 10 seconds
Waiting for result...
Calculating value in background...
Result is: 42

The "async" call in the above program uses the option
"launch::deferred" instead of "launch::async"

We have the "wait" call that is similar to the "get" call but does not return a result.

File: async1b.cpp
#include <iostream>
#include <future>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>

using namespace std ;

int calculate_value()
{
    cout << "Calculating value in background...\n";
    this_thread::sleep_for(chrono::seconds(20)); // Simulate long computation
    return 42;
}

int main()
{
    future<int> future_result = async(launch::async, calculate_value);

    cout << "Main thread continues to execute. Waits for 10 seconds\n";
    this_thread::sleep_for(chrono::seconds(10));
    cout << "Waiting for result...\n";
    future_result.wait(); // Blocks until the result is available

    cout << "function call completed. "  << endl;

    return 0;
}
$ g++ async1b.cpp ; ./a.exe
Main thread continues to execute. Waits for 10 seconds
Calculating value in background...
Waiting for result...
function call completed.
We also have the concept of "promise". This gives us more control over the return value. The async function can set the return value in the middle of the function and it can be retreived in the main thread.
We can also use "wait_for" to check if the async function finished

File: async_wait.cpp
#include <iostream>
#include <future>
#include <chrono>
#include <thread>
#include <string>

using namespace std ;
using namespace chrono_literals; // Enables the use of s, ms, etc.

// A function that simulates a long-running task
string long_running_task()
{
    // Simulate work
    this_thread::sleep_for(chrono::seconds(2));
    return "Task Completed";
}

int main()
{


    cout << "Main thread: Starting asynchronous task..." << endl;

    // Launch the task asynchronously with a specific policy
    future<string> future = async(launch::async, long_running_task);

    cout << "Main thread: Waiting for result with a 1-second timeout check..." << endl;

    // Check the future's status periodically
    while (true)
    {
        // wait_for returns a status indicating if the result is ready, timed out, or deferred
        // wait for 1 second
        future_status status = future.wait_for(1s);

        if (status == future_status::ready)
        {
            cout << "Main thread: Task is ready. Getting result." << endl;
            // Get the result (this call will not block now)
            string result = future.get();
            cout << "Result: " << result << endl;
            break;
        }
        else if (status == future_status::timeout)
        {
            // This happens every 1 second in the loop
            cout << "Main thread: Timeout reached, but task is still running... checking again." << endl;
        }
        // future_status::deferred is also possible if launch::async was not used
    }

    cout << "Main thread: Program finished." << endl;

    return 0;
}

$ g++ async_wait.cpp ; ./a.exe
Main thread: Starting asynchronous task...
Main thread: Waiting for result with a 1-second timeout check...
Main thread: Timeout reached, but task is still running... checking again.
Main thread: Task is ready. Getting result.
Result: Task Completed
Main thread: Program finished.



File: promise1.cpp
#include <iostream>
#include <thread>
#include <future>
#include <chrono>

using namespace std ;

// Function executed in a separate thread
void calculate_sum(int a1, int b1, promise<int>& promise_obj)
{
    cout << "Worker thread: Calculating sum..." << endl;
    // Simulate some long work
    this_thread::sleep_for(chrono::seconds(2));
    int sum = a1 + b1 ;

    // Fulfill the promise by setting the value
    promise_obj.set_value(sum);
    cout << "Worker thread: Value set." << endl  ;
    this_thread::sleep_for( chrono::seconds(20) ) ;
    cout << "Exiting calculate_sum" << endl  ;
}

int main() {
    // 1. Create a promise object for an integer result
    promise<int> promise_obj;

    // 2. Get the associated future object from the promise
    future<int> future_obj = promise_obj.get_future()  ;

    // 3. Launch a worker thread, passing the promise object by reference
    thread worker_thread(calculate_sum, 5, 10, ref(promise_obj))  ;

    // 4. In the main thread, wait for the result using the future
    cout << "Main thread: Waiting for the result..." << endl;

    // get() blocks the current thread until the promise has a value
    //However
    int result = future_obj.get();

    cout << "Main thread: Retrieved result is: " << result << endl;

    // Join the worker thread to the main thread
    worker_thread.join();
    cout << "End of main: " << endl;
    return 0;
}

Exercise

1) Discuss the 2 approaches in the below program.

File: async_ex1.cpp
#include <iostream>
#include <future>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>

using namespace std ;

int globalResult = 0 ;

int calculate_value()
{
    cout << "Calculating value in background...\n";
    this_thread::sleep_for(chrono::seconds(20)); // Simulate long computation
    globalResult = 42 ;
    return 42;
}

int main()
{
    future<int> future_result = async(launch::async, calculate_value);
    cout << "Main thread continues to execute...\n";
    cout << "Waiting for result...\n";
    int result = future_result.get(); // Blocks until the result is available
    cout << "Result is: " << result << endl;

    thread th1( calculate_value ) ;
    th1.join() ;
    cout << "Result is: " << globalResult << endl;


    return 0;
}
















































Solutions

1)