original.roland
original.roland

Reputation: 700

How to start a new jthread on a class member

I think the question is quite obvious. The I have tried so far:

#include <thread>
#include <chrono>

using namespace std::literals::chrono_literals;

class test
{
public:
    void member(std::stop_token stoken)
    {
        std::this_thread::sleep_for(1s);
    }

    void run()
    {
        // None compiles correctly
        // std::jthread jt(&member);
        // std::jthread jt(&test::member, this);
    }
};

int main()
{
    test t;
    t.run();

    return 0;
}

Is it possible with the new jthread & with using stop_token? Ps.: Of course it's possible to workaround it by making the member function static or by removing the stop_token. But I'm curious if there's a real & clean solution instead of extra N lines of hacking.

Upvotes: 4

Views: 1687

Answers (2)

apple apple
apple apple

Reputation: 10604

in addition to existing answer, the reason the code in question doesn't work is because jthread would try to pass stop_token as first parameter


std::jthread jt(&test::member, this);

would do

// with stop_token
// note: stop token is passed as first parameter
std::invoke(&test::member, the_inner_token, this)

// or (without stop_token)
std::invoke(&test::member, this)

which doesn't work because &test::member need to be invoke as

std::invoke(&test::member, this, token)

as a result

#include <thread>

static void before(std::stop_token, int);
static void raw(int);
static void after(int,std::stop_token);

void run(){
    std::jthread(before, 0); // work
    std::jthread(raw, 0);    // work
    std::jthread(after, 0);  // not work
}

Upvotes: 4

康桓瑋
康桓瑋

Reputation: 42861

You can use std::bind_front to bind this to &test::member and pass it to jthread:

#include <thread>
#include <chrono>
#include <functional>

using namespace std::literals::chrono_literals;
class test
{
public:
    void member(std::stop_token stoken)
    {
        std::this_thread::sleep_for(1s);
    }

    void run()
    {
        std::jthread jt(std::bind_front(&test::member, this));
    }
};

int main()
{
    test t;
    t.run();
}

Upvotes: 5

Related Questions