0
votes

I am curious as to how to correctly start a std::thread using an anonymous class call.

With the below code, if my class only having 1 member variable and I call std::thread td(someclass(shared_mutex)); I get a compiler warning of warning C4930: 'std::thread td(someclass)': prototyped function not called (was a variable definition intended?)

However, if I add a second member variable as below and call it with std::thread td(someclass(shared_mutex,x)); I get an error with error C2064: term does not evaluate to a function taking 0 arguments.

class someclass
{ 
private:
  std::mutex& shared_mutex;
  int x;

public:
  someclass(std::mutex& init_mutex, int init_x) :
    shared_mutex(init_mutex),
    x(init_x)
  {}
  //...
};

int main()
{
  std::mutex shared_mutex;
  int x = 10;
  std::thread td(someclass(shared_mutex,x));
  td.join();
  return 0;
}

The only way around this is by creating an void operator()() {} within the class, but is that the correct method, just to have some kind of starting function for the thread reference or am I missing some other point here? I thought the constructor would be resolver for that?

2
What do you want your thread to do? Once you have answered that question, make a function object that does that thing, and pass it to the thread upon construction. Your someclass doesn't actually do anything, so I don't really understand what behaviour you want. - Mankarse
In c++11 (given the tag) you can start threads using lambda expression as argument. You won't have anything more anonymous than that. - oakad
@Mankarse The someclass will actually be a server class that will call another member function within its constructor to try to get an async_accept call. I just wanted to omit lots of code in the example. But even calling a member function from the constructor still is not sufficient unless I have the operator()() function there, which I can move the accept() member function call into, instead of the constructor as used when i didn't call the class in a thread. - Pita
@oakad Do you mean something in the sense of std::thread td([&]{someclass(shared_players_mutex, x);});? Just tried that without the operator()() and that worked. Excellent idea! Thanks for that suggestion! - Pita
@Pita Whatever works for you. But if you're not actually using the capture, then don't capture anything (to avoid hard to detect crashes in the future): []{someclass(...);}. - oakad

2 Answers

1
votes

Try using { and } syntax to construct your object to avoid veximg parses as a function declaration.

std::thread td(someclass(shared_mutex,x))

becomes

std::thread td{someclass{shared_mutex,x}}
0
votes

It seems that you want your thread to execute the long-running constructor of someclass and then immediately discard the newly constructed someclass. This can be done by passing the thread constructor a function object that does just that:

int main()
{
    std::mutex shared_mutex;
    int x = 10;
    std::thread td([&]{someclass(shared_mutex,x);});
    td.join();
    return 0;
}

Be warned: constructing a new thread is a hugely expensive operation, so you should avoid casually spawning new threads if you have the ability to instead reuse existing threads, unless you are only going to create new threads very infrequently.