Я изо всех сил пытаюсь заново выучить C++ и сейчас играю с jthread.
Кажется, у меня все работает при вызове функции-члена класса, которую я хочу, в отдельном потоке.
Однако на самом деле функция никогда не вызывается. Я не могу понять, чего мне здесь не хватает.
Если кто-то сможет указать на мою неизбежную ошибку «ученика», я буду очень признателен.
// includes and directives
#include <iostream>
#include <thread>
#include <functional>
#include <chrono>
// a class for testing stuff
class A {
private:
int updates{ 0 }; // something to count on
int tick{ 1000 }; // tick time set to 1000ms initially
public:
void set_tick(int t) {
tick = (t<1?1:t); // sanity check and set tick time
}
int get_updates() {
return updates; // I did how many?
}
void update(std::stop_token st) {
while (!st.stop_requested()) { // stop if they say stop
updates++; // count this as an update
std::cout << "Performing update" << updates << "\n"; // visually indicate something happened
std::this_thread::sleep_for(std::chrono::milliseconds(tick)); // wait for tick time before doing it all again
}
}
void start() { // start a ticking function
std::cout << "Starting update thread\n"; // tell someone responsible that it's started
std::jthread thr_A(std::bind_front(&A::update, this)); // start the parallel process fucntion in this class
}
};
// main thing
int main()
{
std::cout << "Start main thread\n"; // say that I'm starting up
A a; // make me a sandwich
a.set_tick(10); // really fast(ish)
a.start(); // go on, get on with it
std::this_thread::sleep_for(std::chrono::milliseconds(10000)); // wait until sandwich ready
std::cout << "Wake main thread and terminate\n"; // sandwich is ready, time to eat
}
Ваш экземпляр jthread выходит из области действия, как только start достигает своего конца. Затем автоматически вызывается деструктор jthread, который, в свою очередь, вызывает член request_stop и join на нем. Это потому, что thr_A — это автоматический объект, локальный для start.
Примечание: альтернативой использованию std::bind является использование лямбда-выражения . Например. std::jthread thread{[this]{ update(); };. Лямбда-выражения также часто используются в сочетании с алгоритмами стандартной библиотеки.





thr_A определяется как локальная переменная в start().
Он уничтожается, когда выходит за пределы области действия, т.е. когда start() возвращается.
Поскольку это jthread, при уничтожении его просят остановить, а затем joined.
Поскольку start() возвращается сразу после запуска thr_A, у потока практически нет возможности запуститься.
Возможным решением может быть добавление thr_A в качестве члена class A. Это означает, что его деструктор будет вызываться только тогда, когда ваш a будет уничтожен — в вашем случае: когда main() выйдет.
Таким образом, поток выполнит всю ожидаемую вами логику.
Примечание: в живой демонстрации я уменьшил sleep_for в main(), чтобы избежать тайм-аута Godbolt.
Я знал, что где-то это будет ошибкой новичка. Теперь я точно понимаю, что вы имеете в виду! Спасибо всем за помощь! Да, я тоже буду переписывать, используя лямбда-выражение, чтобы снова во всем разобраться.
@Radiobiscuit рад помочь! И да, лямбда-выражения — это очень полезно, и их стоит изучить.
thr_Aсразу же отвлекается, когдаstartвозвращается. Поскольку этоjthread, его просят остановиться иjoined. У него едва ли есть шанс побежать.