In C++, std::future and std::async are part of the C++11 standard’s concurrency library. They allow you to run tasks asynchronously and obtain results later, making them useful for writing non-blocking code and parallelizing computations. Here’s a breakdown of how they work and how they’re typically used:
C++ std::async
std::async is a high-level function that allows you to launch a task (a callable, such as a function or lambda) asynchronously. You specify a function to run, and std::async returns a std::future that represents the result of the function. You can later retrieve this result, either when the task completes or whenever you need it.
#include <iostream>
#include <future>
#include <chrono>
int compute() {
std::this_thread::sleep_for(std::chrono::seconds(2)); // Simulate work
return 42; // Result of the computation
}
int main() {
// Launch the task asynchronously
std::future<int> result = std::async(std::launch::async, compute);
// Perform other tasks while compute() is running...
// Get the result of compute() (this will wait if the task isn’t done)
int value = result.get();
std::cout << "Result: " << value << std::endl;
return 0;
}
In this example:
- std::async(std::launch::async, compute) launches compute() asynchronously, returning a std::future object.
- The result.get() call waits for the task to complete if it hasn’t yet finished and then retrieves the result.
C++ std::launch Policy
- std::launch::async: Forces the task to run asynchronously on a new thread.
- std::launch::deferred: Delays execution until get() or wait() is called on the future, effectively making it synchronous.
If you omit the policy, C++ may choose either, depending on implementation-defined criteria.
C++ std::future
std::future is a class template that represents a result to be obtained later. It’s essentially a placeholder for the result of an asynchronous operation.
Key Methods
- get(): Waits for the result if it hasn’t finished and then retrieves it. After calling get(), the std::future becomes empty.
- wait(): Waits until the task completes, but doesn’t retrieve the result.
- valid(): Returns true if the std::future has a shared state (i.e., a result is available).
- wait_for() and wait_until(): Wait for a specific amount of time or until a deadline for the result to be available.
Example with wait_for
if (result.wait_for(std::chrono::seconds(1)) == std::future_status::ready) {
std::cout << "Result is ready: " << result.get() << std::endl;
} else {
std::cout << "Still waiting for the result..." << std::endl;
}
This code checks if the result is ready within 1 second. If not, it continues without blocking.
C++ std::promise
For more advanced use, std::promise allows you to manually set the result of a std::future. A std::promise object provides a std::future, and you set the result explicitly.
#include <iostream>
#include <future>
#include <thread>
void setPromise(std::promise<int> p) {
p.set_value(10); // Set the result of the promise
}
int main() {
std::promise<int> p;
std::future<int> f = p.get_future(); // Get the future from the promise
std::thread t(setPromise, std::move(p)); // Pass the promise to a thread
t.join();
std::cout << "Result from promise: " << f.get() << std::endl; // Get the result
return 0;
}
In this example, the result 10 is set by std::promise, which std::future can retrieve with f.get().
C++ Future/Async/Promise Summary
- std::async: Launches a task that runs asynchronously, returning a std::future.
- std::future: Represents a value that will be set in the future, usually the return value of an asynchronous task.
- std::promise: Allows manually setting the result for a std::future.
Using these, you can effectively manage asynchronous tasks in C++, making it easier to run computations in parallel or offload work to other threads without blocking the main thread.
C/C++ Programming
- Understanding std::transform_reduce in Modern C++
- Implement a Lock Acquire and Release in C++
- Detecting Compile-time vs Runtime in C++: if consteval vs std::is_constant_evaluated()
- C++ Forward References: The Key to Perfect Forwarding
- Understanding dynamic_cast in C++: Safe Downcasting Explained
- C vs C++: Understanding the restrict Keyword and its Role in Optimization
- C++ Lvalue, Rvalue and Rvalue References
- C++ assert vs static_assert
- Why auto_ptr is Deprecated in C++?
- C++ What is the consteval? How is it different to const and constexpr?
- Tutorial on C++ std::move (Transfer Ownership)
- const vs constexpr in C++
- Tutorial on C++ Ranges
- Tutorial on C++ Smart Pointers
- Tutorial on C++ Future, Async and Promise
- The Memory Manager in C/C++: Heap vs Stack
- The String Memory Comparision Function memcmp() in C/C++
- Modern C++ Language Features
- Comparisions of push_back() and emplace_back() in C++ std::vector
- C++ Coding Reference: is_sorted_until() and is_sorted()
- C++ Coding Reference: iota() Setting Incrementing Values to Arrays or Vectors
- C++ Coding Reference: next_permutation() and prev_permutation()
- C++ Coding Reference: count() and count_if()
- C++ Code Reference: std::accumulate() and Examples
- C++ Coding Reference: sort() and stable_sort()
- The Next Permutation Algorithm in C++ std::next_permutation()
–EOF (The Ultimate Computing & Technology Blog) –
854 wordsLast Post: Teaching Kids Programming - Delete Nodes From Linked List Present in Array
Next Post: Understanding Availability Percentages: Calculating Downtime for Your Systems