Search code examples
c++multithreadingc++11pthreadsstdthread

Passing reference to object in callback function to std::thread


I'm trying to do something like this:

void commands_conn_handler(int socket, RPiServer& server) {
  // Not important code about handling connection
}

class RPiServer {
public:
  void Accept(void Accept(void (*acceped_conn_handler)(int, RPiServer&)) {
    // (...)
    int remote_socket = 0; // Doesn't matter - example.
    std::thread conn_handler_thread(acceped_conn_handler, remote_socket, *this);
    conn_handler_thread.join();
  }
};

int main() {
  RPiServer commands_server();
  commands_server.Accept(commands_conn_handler);
}

And when I try to build this, there are some errors:

In file included from /usr/include/c++/6/thread:39:0, from src/rpi_server/rpiserver.cpp:11: /usr/include/c++/6/functional: In instantiation of ‘struct std::_Bind_simple’: /usr/include/c++/6/thread:138:26: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (*&)(int, RPiServer&); _Args = {int&, RPiServer&}]’ src/rpi_server/rpiserver.cpp:89:79: required from here /usr/include/c++/6/functional:1365:61: error: no type named ‘type’ in ‘class std::result_of’ typedef typename result_of<_Callable(_Args...)>::type result_type; ^~~~~~~~~~~ /usr/include/c++/6/functional:1386:9: error: no type named ‘type’ in ‘class std::result_of’ _M_invoke(_Index_tuple<_Indices...>) ^~~~~~~~~ Makefile:29: recipe for target 'build/rpi_server/rpiserver.o' failed

When I change thread function in following way (remove reference to object):

void commands_conn_handler(int socket) {
  // Not important code about handling connection
}

class RPiServer {
public:
  void Accept(void (*acceped_conn_handler)(int)) {
    // (...)
    int remote_socket = 0; // Doesn't matter - example.
    std::thread conn_handler_thread(acceped_conn_handler, remote_socket);
    conn_handler_thread.join();
  }
};

int main() {
  RPiServer commands_server();
  commands_server.Accept(commands_conn_handler);
}

Everything builds perfectly fine. What I'm doing wrong when I'm passing reference as parameter to thread function?


Solution

  • So here you have a working example:

    #include <thread>
    #include <functional>
    class RPiServer;
    
    void commands_conn_handler(int socket, RPiServer &server) {
        // Not important code about handling connection
    }
    
    class RPiServer {
    public:
        void Accept(void (*acceped_conn_handler)(int, RPiServer&)) {
            // (...)
            int remote_socket = 0; // Doesn't matter - example.
            std::thread conn_handler_thread(acceped_conn_handler, remote_socket, std::ref(*this));
            conn_handler_thread.join();
        }
    };
    
    int main() {
        RPiServer commands_server;
        commands_server.Accept(commands_conn_handler);
    }
    

    The error you was getting was because you were not providing correct type for the constructor of conn_handler_thread. To explicitly get a reference to an object (which you need to do here), use a std::ref() function.

    P.S.: Also you copy pasted your code example wrong, duplicating the void Accept part. You also had a most vexing parse error in main().