New thread in C ++ 20: std :: jthread

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.








All Articles