2

I'm trying to use mutex to synchronise the execution of several methods in different threads. I create a class Bar that contains a foo method and a mutex attribute. Then I want to run that foo method in a thread. I don't understand why it is a problem and the following code does not compile? And how to fix this? Any help appreciated.

#include <thread>
#include <mutex>

class Bar
{
public:
  Bar (){};
  void foo(){};
  std::mutex m_;
};

int main(void)
{
  Bar b;
  std::thread t(&Bar::foo, b);
  return 0;
}

I'm getting the following errors:

include/c++/7.3.0/thread:256:11: error: no matching constructor for initialization of '__decayed_tuple<void (Bar::*)(), Bar &>'                  (aka 'std::tuple<void (Bar::*)(), Bar>')                                                                                                                                                             
 return { __decayed_tuple<_Callable, _Args...>{ 

and

include/c++/7.3.0/tuple:133:4: error: call to implicitly-deleted copy constructor of 'Bar'
        : _M_head_impl(std::forward<_UHead>(__h)) { }
  • 1
    Instead of passing a `Bar` object, pass the address of `Bar` to the thread constructor.. `std::thread t(&Bar::foo, &b);` – LWimsey Sep 01 '18 at 19:15
  • `thread` prefers copies, but if you copy the object you have two copies and two mutexes (and two mutexes is so pointless that it's not allowed). Likely not what you want. A [reference wrapper](https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper) seems the most ideological option without a redesign. With more context in the question someone may be able to offer a better path to take. – user4581301 Sep 01 '18 at 19:20
  • Possibly helpful reading: [How should I deal with mutexes in movable types in C++?](https://stackoverflow.com/questions/29986208/how-should-i-deal-with-mutexes-in-movable-types-in-c) – user4581301 Sep 01 '18 at 19:23
  • The latter error is due to the former; fix the former and the latter will go away as well. – WhozCraig Sep 01 '18 at 19:24
  • Prior to end of main (and with PlinyTheElder's fix.), you probably should t.join(); Without the join, Ubuntu reports "terminate called without an active exception" With the join, normal termination. – 2785528 Sep 01 '18 at 19:57

1 Answers1

3

You should be passing the pointer to b, not b itself:

std::thread t(&Bar::foo, &b);

The way it is in your code, you are trying to pass by value, which involves copying - and the mutex does not have a copy constructor, only a move constructor.

PlinyTheElder
  • 1,454
  • 1
  • 10
  • 15