Hello, Habr! The translation of the article was prepared as part of the " C ++ Developer. Professional " course
CppCon 2018 : « std::thread
(interrupted)?». — , . C++20 std::jthread
( — . ).
, CppCon 2018. , , (). , P0660: Cooperatively Interruptible Joining Thread. . , ( ). C++. C++.
Cooperatively Interruptible Joining Thread ( ) , : (interruptible) (automatically joining, «» — , join()
— . ). .
std::thread
. std::thread
joinable
, std::terminate
. thr
joinable
, thr.join()
, thr.detach()
.
// threadJoinable.cpp
#include <iostream>
#include <thread>
int main(){
std::cout << std::endl;
std::cout << std::boolalpha;
std::thread thr{[]{ std::cout << "Joinable std::thread" << std::endl; }};
std::cout << "thr.joinable(): " << thr.joinable() << std::endl;
std::cout << std::endl;
}
.
. th
, : «Joinable std::thread»
.
<thread>
"jthread.hpp
" std::jthread
C++.
// jthreadJoinable.cpp
#include <iostream>
#include "jthread.hpp"
int main(){
std::cout << std::endl;
std::cout << std::boolalpha;
std::jthread thr{[]{ std::cout << "Joinable std::thread" << std::endl; }};
std::cout << "thr.joinable(): " << thr.joinable() << std::endl;
std::cout << std::endl;
}
thr
, joinable
, , , .
std::jthread
, .
// interruptJthread.cpp
#include "jthread.hpp"
#include <chrono>
#include <iostream>
using namespace::std::literals;
int main(){
std::cout << std::endl;
std::jthread nonInterruptable([]{ // (1)
int counter{0};
while (counter < 10){
std::this_thread::sleep_for(0.2s);
std::cerr << "nonInterruptable: " << counter << std::endl;
++counter;
}
});
std::jthread interruptable([](std::interrupt_token itoken){ // (2)
int counter{0};
while (counter < 10){
std::this_thread::sleep_for(0.2s);
if (itoken.is_interrupted()) return; // (3)
std::cerr << "interruptable: " << counter << std::endl;
++counter;
}
});
std::this_thread::sleep_for(1s);
std::cerr << std::endl;
std::cerr << "Main thread interrupts both jthreads" << std:: endl;
nonInterruptable.interrupt();
interruptable.interrupt(); // (4)
std::cout << std::endl;
}
main , nonInterruptable
, , interruptable
, ( 1 2). nonInterruptable
, interruptable
, std::interrupt_token
3, , : itoken.is_interrupted()
. return
, , . interruptable.interrupt()
( 4) . nonInterruptable.interrupt()
nonInterruptable
, , , .
(interrupt tokens), .
std::interrupt_token
(shared ownership) , . : valid
, is_interrupted
, interrupt
.
itoken.valid() — true
,
itoken.is_interrupted() — true
, true
interrupt()
itoken.interrupt()
— !valid()
is_interrupted()
, . , itoken.is_interrupted() == true
. is_interrupted()
, . . , .
std::jthread jthr([](std::interrupt_token itoken){
...
std::interrupt_token interruptDisabled;
std::swap(itoken, interruptDisabled); // (1)
...
std::swap(itoken, interruptDisabled); // (2)
...
}
std::interrupt_token interruptDisabled
. , (1) (2), (2) .
std::jhread
std::thread
, . std::interrupt_token
.
Wait
wait wait_for
wait_until
std::condition_variable
. std::interrupt_token
.
template <class Predicate>
bool wait_until(unique_lock<mutex>& lock,
Predicate pred,
interrupt_token itoken);
template <class Rep, class Period, class Predicate>
bool wait_for(unique_lock<mutex>& lock,
const chrono::duration<Rep, Period>& rel_time,
Predicate pred,
interrupt_token itoken);
template <class Clock, class Duration, class Predicate>
bool wait_until(unique_lock<mutex>& lock,
const chrono::time_point<Clock, Duration>& abs_time,
Predicate pred,
interrupt_token itoken);
. , std::interrupt_token itoken
. wait
, .
cv.wait_until(lock, predicate, itoken);
if (itoken.is_interrupted()){
// interrupt occurred
}
?
, (concepts).
"C++ Developer. Professional".
- « »: unit- googletest.