Software Engineering: Collaboratively Suspending a Thread in C++20

0
38
Software Engineering: Collaboratively Suspending a Thread in C++20


This article is a repeat of a post I originally wrote three and a half years ago. I need this as a starter for the next article. So, I decided to republish the post.

Advertisement





Rainer Grimm has been working as a software architect, team and training manager for many years. He enjoys writing articles on the programming languages ​​C++, Python and Haskell, but also frequently speaking at specialist conferences. On his blog Modern C++ he discusses his passion C++ in depth.


Collaboratively suspending a thread in C++20

Collaboratively suspending a thread in C++20

First, why is it not a good idea to terminate a thread? The answer is simple. You don’t know what state the thread is in when you terminate it. There are two potential dangers:

  • The threads may finish their job only partially. Of course, the state of their job and hence the state of the program is now unknown. Ultimately, this leads to undefined behavior and no reliable statements about the program are possible anymore.
  • The thread may currently be in a critical region and the mutex may be locked. If the thread terminates in this stage, it will likely cause a deadlock.

It’s not a good idea to abruptly interrupt a thread. It’s better to ask politely if you want the thread to terminate. This is what cooperative breaking means in C++20. You politely ask the thread if it wants to terminate, and the thread can either honor your request or ignore it.

Additional cooperative break capability in C++20 based on three new data types std::stop_token, std::stop_callback And std::stop_source. They allow a thread to terminate a thread asynchronously or ask whether the thread has received a stop signal. std::stop_token can be assigned to an operation for this purpose. This stop token can be used to ask the operation if a request to terminate has been sent to it. On the other hand, you can std::stop_token Using a callback std::stop_callback be recorded. The stop request is made by std::stop_source Sent. Your signal affects all affiliates std::stop_token. Three classes std::stop_source, std::stop_token And std::stop_callback Share ownership of the related stop position. Call request_stop(), stop_requested() And stop_possible() There are atoms.

A std::stop_source Can be made in two ways:

stop_source();                                     // (1)
explicit stop_source(std::nostopstate_t) noexcept; // (2)

Creates a default constructor (1) std::stop_source with stopping condition. Manufacturer, std::nostopstate_t takes as an argument generates a std::stop_source without an associated stop condition.

Constituent std::stop_source src Provides the following methods for handling stop requests:

Zepp Health integrates OpenAI-GPT-4o into the Amazfit smartwatchZepp Health integrates OpenAI-GPT-4o into the Amazfit smartwatch


Collaboratively suspending a thread in C++20

Collaboratively suspending a thread in C++20

src.stop_possible() means that src There is an associated stop condition. src.stop_requested() then gives it again true back if src There is an associated stop condition and it has not been requested to stop before. Call src.get_token() Returns the stop token. Thanks to it, you can check whether a stop request has already been made or can be made.

Stop Token stoken Stops inspecting the source src. The following table presents the methods std::stop_token stoken First:


Collaboratively suspending a thread in C++20

Collaboratively suspending a thread in C++20

Default-constructed tokens have no associated stop conditions. stoken.stop_possible gives true back if stoken There is an associated stop condition. stoken_stop_requested() then gives it again true This is returned if the stop token has an associated stop status and has already received a stop request.

If std::stop_token If you want to temporarily disable it, it can be replaced with a default-constructed token. It has no associated stop state. The following lines show how to temporarily disable the thread’s ability to receive stop requests:

std::jthread jthr(()(std::stop_token stoken) {
    ...
    std::stop_token interruptDisabled;
    std::swap(stoken, interruptDisabled);  // (1)
    ...                                    // (2)
    std::swap(stoken, interruptDisabled);
    ...
}

std::stop_token interruptDisabled There is no associated stop condition. i.e. the thread jthr All lines except (1) and (2) can accept stop requests.

If you study the code snippet carefully, you will be fine std::jthread But. std::jthread C++20 has an extended std::thread From C++11. In “J” jthread stands for joinableBecause one std::jthread automatically combined into its destructor. Originally this new formula was called ithread: “I” means disruptive. I put std::jthread In more detail in the next article.

The next example shows how std::jthread Can be used together with callbacks:

// invokeCallback.cpp

#include 
#include 
#include 
#include 

using namespace::std::literals;

auto func = ()(std::stop_token stoken) {                    // (1)
  int counter{0};
  auto thread_id = std::this_thread::get_id();
  std::stop_callback callBack(stoken, (&counter, thread_id) // (2)
  {
    std::cout << "Thread id: " << thread_id 
                  << "; counter: " << counter << '\n';
  });
  while (counter < 10) {
    std::this_thread::sleep_for(0.2s);
    ++counter;
  }
};

int main() {
    
  std::cout << '\n';
    
  std::vector<:jthread> vecThreads(10);
  for(auto& thr: vecThreads) thr = std::jthread(func);
    
  std::this_thread::sleep_for(1s);                          // (3)
    
  for(auto& thr: vecThreads) thr.request_stop();            // (4)

  std::cout << '\n';
    
}

Each of the ten threads calls the lambda function func (1) on the callback (2) representing the ID of the thread and the counter, thanks to a one second sleep mainThread (3) and child thread are sleeping, value of counter is 4 at the time of callback call thr.request_stop() (4) Initiates a callback on each thread.


Collaboratively suspending a thread in C++20

Collaboratively suspending a thread in C++20


(RME)

Authy: Hackers access millions of phone numbers through an unsecured APIAuthy: Hackers access millions of phone numbers through an unsecured API

LEAVE A REPLY

Please enter your comment!
Please enter your name here