简体   繁体   中英

std::thread, start thread on `this' (from within the class itself)

I'm trying to create a class which starts a thread-instance of a one of its member methods. When I do in main:

test myinstance;
std::thread mythread(myinstance);

then things compile. But using the following construction:

#include <stdio.h>
#include <unistd.h>
#include <thread>

class test
{
        std::thread *pt;
public:
        test()
        {
                pt = new std::thread(this);
        }

        void operator()() const
        {
                printf("thread start\n");
                sleep(5);
                printf("thread end\n");
        }
};

int main(int arg, char *argv[])
{
        test ptest;
        sleep(10);

        return 0;
}

I get the following error:

folkert@here:~$ g++ -std=c++0x test.cpp In file included from /usr/include/c++/4.6/thread:39:0, from test.cpp:3: /usr/include/c++/4.6/functional: In member function 'void std::_Bind_result<_Result, _Functor(_Bound_args ...)>::__call(std::tuple<_Args ...>&&, std::_Index_tuple<_Indexes ...>, typename std::_Bind_result<_Result, _Functor(_Bound_args ...)>::__enable_if_void<_Res>::type) [with _Res = void, _Args = {}, int ..._Indexes = {}, _Result = void, _Functor = test*, _Bound_args = {}, typename std::_Bind_result<_Result, _Functor(_Bound_args ...)>::__enable_if_void<_Res>::type = int]': /usr/include/c++/4.6/functional:1378:24: instantiated from 'std::_Bind_result<_Result, _Functor(_Bound_args ...)>::result_type std::_Bind_result<_Result, _Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {}, _Result = void, _Functor = test*, _Bound_args = {}, std::_Bind_result<_Result, _Functor(_Bound_args ...)>::result_type = void]' /usr/include/c++/4.6/thread:117:13: instantiated from 'v oid std::thread::_Impl<_Callable>::_M_run() [with _Callable = std::_Bind_result]' test.cpp:28:1: instantiated from here /usr/include/c++/4.6/functional:1287:4: error: '((std::_Bind_result*)this)->std::_Bind_result::_M_f' cannot be used as a function

So my guess is that it won't work this way . My question now is: how can I, using std::thread, let a class start a thread of one of its own methods?

One of std::thread s constructors looks like this:

template<typename Callable>
    explicit thread(Callable func);

This requires you to pass something that is callable , that means it can be invoked with operator() . What you're passing to your std::thread is not callable.

You cannot call this . this is a pointer to the current object, it is not callable.

You need pass a member function or other function into your std::thread constructor.

You could also create a functor and pass that, as that is callable.

EDIT: Just noticed have indeed overloaded operator() , to call it, you have do the follwowing:

  test t;
  std::thread my_thread(t); //invokes operator() on test.

//also remove this statement from your ctor:  pt = new std::thread(this);

Many fixes:

#include <iostream>
#include <thread>

struct test
{
    void operator()() const
    {
        std::cout << "thread start\n";
        sleep(5);
        std::cout << "thread end\n";
    }
};

int main(int arg, char *argv[])
{
    std::thread pt(std::move(test()));

    pt.join();
    return 0;
}

Fixes

  • separation of concerns (you can run test without a thread now, yay!)
  • leaking the std::thread instance (memory + resource)
  • not (deterministically) waiting for the thread to finish; this is UB even if you think you know that sleep will run longer
  • Note how avoid the local/copy of ptest by doing a move. Technically, std::move is redundant there, but I like things specific and you'd run into the most vexing parse :

     std::thread pt((test())); 

Try this.

pt = new std::thread( std::ref( *this ) );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM