C++ 20 – <stop_token> Header
Last Updated :
06 Jun, 2023
C++20 has introduced the <stop_token> Header, presenting an alternative method for canceling asynchronous operations. A new class std::stop_token is provided by the <stop_token> header that allows for seamless communication of a termination request between two threads.
In this article, we will discuss the basics of <stop_token> and how to use it in C++20.
Classes in <stop_token> Header
The <stop_token> header file contains 2 main classes which are:
- stop_source: The stop_source class is used to request cancellation.
- stop_token: The stop_token class is used to check if there is a need to issue the cancellation.
std::stop_token Class
The std::stop_token is a class that provides a way to call off asynchronous operation requests. It is equivalent to a token that can be transferred through different program fragments, providing the ability to notify about the cancellation of an ongoing process. Interestingly, the std::stop_token objects are highly convenient as they can be easily moved and copied, without adding much burden to the system’s processing.
Syntax
stop_token token_name = token;
std::stop_token Member Methods
The two primary functions of the std::stop_token class are:
- stop_requested(): This function responds with a value of true when a cancellation request has been made, otherwise, it returns false.
- stop_possible(): This function returns true if the related std::stop_source object can be utilized to request a cancellation, otherwise it returns false.
Examples of stop_token
Example 1
In the below code, we will make use of the above syntax to demonstrate the use of the <stop_token> Header.
C++
#include <chrono>
#include <iostream>
#include <stop_token>
#include <thread>
using namespace std;
void worker(stop_token stopToken)
{
while (!stopToken.stop_requested()) {
cout << "Working..." << endl;
this_thread::sleep_for(chrono::seconds(1));
}
cout << "Cancelled." << endl;
}
int main()
{
stop_source stopSource;
stop_token stopToken = stopSource.get_token();
thread t(worker, stopToken);
this_thread::sleep_for(chrono::seconds(5));
stopSource.request_stop();
t.join();
return 0;
}
|
Output
Working...
Working...
Working...
Working...
Working...
Cancelled.
Explanation: In this example, A novel std::stop_source is established along with its associate, a std::stop_token. After passing the stopToken object as a parameter to the worker function, a new thread is initiated.
The worker function employs the stop_requested() function to verify if there are any cancellation petitions. After waiting for approximately 5 seconds, it seeks for cancellation by requesting the stopSource object to stop via the request_stop() function. Finally, we join the thread and exit the program.
Example 2
C++
#include <chrono>
#include <iostream>
#include <stop_token>
#include <thread>
using namespace std;
class Worker {
public :
void run(stop_token stopToken)
{
while (!stopToken.stop_requested()) {
cout << "Working..." << endl;
this_thread::sleep_for(chrono::seconds(1));
}
cout << "Cancelled." << endl;
}
};
int main()
{
stop_source stopSource;
stop_token stopToken = stopSource.get_token();
Worker worker;
thread t(&Worker::run, &worker, stopToken);
this_thread::sleep_for(chrono::seconds(5));
stopSource.request_stop();
t.join();
return 0;
}
|
Output
Working...
Working...
Working...
Cancelled.
Explanation: In this example, Upon defining a class named Worker, we create a function run that expects a stopToken of std::type to be passed as a parameter. We initiate a thread to run the Worker object’s run method, providing the stopToken object as an argument. The run method frequently checks the stop_requested() function of the stopToken object to ensure that the cancellation requests are taken into consideration.
Advantages of stop_token
The advantages of using stop_token are as follows:
- Efficient and lightweight: It provides a lightweight and efficient way of canceling asynchronous operations. The std::stop_token class is lightweight and can be copied and moved efficiently.
- More elegant and thread-safe: It avoids the need for manual cancellation flags and provides a more elegant and thread-safe way of canceling operations. This makes it easier to write robust and efficient code.
- Interoperability: It is designed to be interoperable with other C++20 concurrency features such as coroutines and futures. This makes it easier to write complex concurrent programs.
- Scalable and flexible: It is scalable and flexible, making it suitable for a wide range of applications, from simple programs to complex systems. It allows for fine-grained control over the cancellation of asynchronous operations.
- Standardized: It is part of the C++20 standard library, which means that it is widely available and supported by many compilers and tools.
Share your thoughts in the comments
Please Login to comment...