Как передать функцию с аргументами и stop_condition в jthread? - PullRequest
3 голосов
/ 19 февраля 2020

Я пытаюсь сделать что-то подобное

#include <iostream>
#include <thread>
#include <chrono>

void doWork(char a, std::stop_token st = {}) {
    while (!st.stop_requested()) {
        std::cout << a << '\n';
    }
}

int main() {
    std::jthread t1{doWork, 'A'}, // error
                 t2{doWork, 'B'}; // error
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
}

Но он не скомпилируется на магистрали g cc с -std=c++2a:

/opt/compiler-explorer/gcc-trunk-20200219/include/c++/10.0.1/thread:537:20: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues

  537 |      static_assert(is_invocable_v<decay_t<_Callable>,

      |                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  538 |       decay_t<_Args>...>,

      |       ~~~~~~~~~~~~~~~~~~

Возможно ли это вообще сделать что-то вроде этого?

Я предположил, что это должно быть возможно, потому что я видел подобный пример с лямбда ( здесь ):

//...
std::jthread t([&ready, &readyMutex, &readyCV] (std::stop_token st) {
    while (!stoken.stop_requested()) {
        //...
    }
});

1 Ответ

5 голосов
/ 19 февраля 2020

Вы почти правы в своей реализации. Ограничение для вызываемого заключается в том, что он принимает std::stop_token в качестве первого аргумента. Таким образом, переключение порядка в объявлении doWork приведет к его сортировке.

void doWork(std::stop_token st, char a) {
    while (!st.stop_requested()) {
        std::cout << a << '\n';
    }
}

Токен происходит из реализации библиотеки, поэтому его конструкция не должна вас беспокоить.

...