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?
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}}
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.
Related
I would like to assign a name to a thread, the thread itself must do this. The thread is a class member of the class foo.
I would like to start this thread with a lambda but unfortunately I get the error message:
no match for call to '(std::thread) (foo::start()::<lambda()>)
Can someone explain to me where the problem is?
Previously I had created a temporary thread object, and put this with move on the thread "manage", however, I can then give no name.
class foo {
public:
int start()
{
this->manage([this](){
auto nto_errno = pthread_setname_np(manage.native_handle(),"manage"); // Give thread an human readable name (non portable!)
while(1){
printf("do work");
}
});
return 1;
}
private:
int retVal;
std::thread manage;
};
You passed the lambda in a wrong way, after initialization the manage thread can't be initialized again. you should create a new std::thread and assign it.
the following compiles and indeed prints "manage".
class foo {
public:
int start()
{
manage = std::thread([this]{
auto nto_errno = pthread_setname_np(manage.native_handle(),"manage");
char name[16];
pthread_getname_np(pthread_self(), &name[0], sizeof(name));
cout << name << endl;
});
manage.join();
return 1;
}
private:
int retVal;
std::thread manage;
};
I am in the process of writing a multithreaded TCP server. I am going to have one thread handle incoming socket connections, and spin off threads to handle the communication on those sockets. However, I want the thread handling socket connections to take as parameters a callback function with supporting parameters, and the compiler is complaining. Here is code to illustrate my problem:
template<class Function, class... Args>
void handleIncomingConnectionRequests(Function&& f, Args... args)
{
f(args...);
}
void callback(int x)
{
std::cout << x << "\n";
}
void main()
{
std::thread handleIncomingConnectionsThread(handleIncomingConnectionRequests<decltype(callback)>, callback, 5);
handleIncomingConnectionsThread.join();
}
When I attempt to compile this with clang on Windows, I get a fairly large compilation stack error, but the relevant issue seems to be the following:
error: too few arguments to function call, expected 1, have 0
f(args...);
Why does args appear to have no parameters? I'm clearly passing two arguments to the std::thread constructor. I have clearly done something wrong in the way I am passing the variables in, but I'm not sure how to resolve the issue.
EDIT: It was pointed out that I failed to define the second template argument. I have updated the code to read:
template<class Function, class... Args>
void handleIncomingConnectionRequests(Function&& f, Args... args)
{
f(args...);
}
void callback(int x)
{
std::cout << x << "\n";
}
void main()
{
std::thread handleIncomingConnectionsThread(handleIncomingConnectionRequests<decltype(callback), int>, callback, 5);
handleIncomingConnectionsThread.join();
}
I now get this error:
error: no matching function for call to 'invoke'
This error comes from the xthread file, part of the implementation of the C++ standard library for the thread include file.
Change
std::thread handleIncomingConnectionsThread(handleIncomingConnectionRequests<decltype(callback), int>, callback, 5);
to
std::thread handleIncomingConnectionsThread(handleIncomingConnectionRequests<decltype(callback)*, int>, callback, 5);
or
std::thread handleIncomingConnectionsThread(handleIncomingConnectionRequests<decltype(&callback), int>, callback, 5);
I'd like to have a wrapper thread function, i.e. a function executed by a thread which does some extra stuff, and then calls the user function.
template<class F, class... Args>
void wrapper(F&& user_function, Args&&... args) {
// do some extra stuff
user_function(args); // maybe I need to forward args
// do some extra stuff
}
Ok, this could be a nice wrapper, so I need a manager that uses this wrapper function and allows the user to spawn his own threads:
class ThreadManager {
public:
template<class F, class... Args>
std::thread newThread(F&& f, Args&&... args) {
return std::thread(thread_wrapper<F,Args...>, std::forward<F>(f), std::forward<Args>(args)...);
}
};
this way the thread manager SHOULD spawn a thread that uses the wrapper function which, in turn, does its extra work and calls the user function.
But the compiler now says: Attempt to use a deleted function.
The error is in the thread header:
template <class _Fp, class ..._Args, size_t ..._Indices>
inline _LIBCPP_INLINE_VISIBILITY
void
__thread_execute(tuple<_Fp, _Args...>& __t, __tuple_indices<_Indices...>)
{
__invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
}
What am I missing/doing wrong?
[edit]
Using test:
void foo(int i) {
std::cout << "foo: " << i << std::endl;
}
int main(int argc, const char *argv[]) {
ThreadManager mgr;
auto t = mgr.newThread(foo, 10);
t.detach();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
return 0;
}
I'm using Xcode 7.1 with LLVM compiler, but fails on FreeBSD clang 3.3 too.
The Xcode error is:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/thread:337:5: error: attempt to use a deleted function
__invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/thread:347:5: note: in instantiation of function template specialization 'std::__1::__thread_execute' requested here
__thread_execute(*__p, _Index());
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/thread:359:42: note: in instantiation of function template specialization 'std::__1::__thread_proxy >' requested here
int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get());
I'm not sure what is causing the "Attempt to use a deleted function" in your example, I get other errors related to std::thread's bind mechanism.
It appears the way you are spelling out the template arguments for thread_wrapper is not playing nice with std::thread's constructor - in particular when it uses a simplified std::bind internally. The mix of perfectly forwarded function types and std::decayed function pointers seems to upset std::result_of.
we can make it work by applying some std::decay in newThread ourselves:
return std::thread( thread_wrapper<typename std::decay<F>::type,
typename std::decay<Args>::type...>,
std::forward<F>(f),
std::forward<Args>(args)... );
...but to be honest I'm not entirely sure why that works.
Alternatively, with some indirection and more forwarding, we can avoid having to spell out the template arguments.
We just need a functor that forwards to thread_wrapper (or a polymorphic lambda in C++14):
struct wrapper_helper {
template<class F, class... Args>
void operator()(F&& f, Args&&... args) const {
thread_wrapper(std::forward<F>(f), std::forward<Args>(args)...);
}
};
And use it in newThread:
return std::thread(wrapper_helper{}, std::forward<F>(f), std::forward<Args>(args)...);
Here's the full example showing arguments passed by value, reference and rvalue reference working as intended: http://coliru.stacked-crooked.com/a/b75d5a264f583237
Note: For move-only types like std::unique_ptr, you will definitely want to forward args... in thread_wrapper.
I'm writing some threaded C++11 code, and I'm not totally sure on when I need to use a memory fence or something. So here is basically what I'm doing:
class Worker
{
std::string arg1;
int arg2;
int arg3;
std::thread thread;
public:
Worker( std::string arg1, int arg2, int arg3 )
{
this->arg1 = arg1;
this->arg2 = arg2;
this->arg3 = arg3;
}
void DoWork()
{
this->thread = std::thread( &Worker::Work, this );
}
private:
Work()
{
// Do stuff with args
}
}
int main()
{
Worker worker( "some data", 1, 2 );
worker.DoWork();
// Wait for it to finish
return 0;
}
I was wondering, what steps do I need to take to make sure that the args are safe to access in the Work() function which runs on another thread. Is it enough that it's written in the constructor, and then the thread is created in a separate function? Or do I need a memory fence, and how do I make a memory fence to make sure all 3 args are written by the main thread, and then read by the Worker thread?
Thanks for any help!
The C++11 standard section 30.3.1.2 thread constructors [thread.thread.constr] p5 describes the constructor template <class F, class... Args> explicit thread(F&& f, Args&&... args):
Synchronization: the completion of the invocation of the constructor synchronizes with the beginning of the invocation of the copy of f.
So everything in the current thread happens before the thread function is called. You don't need to do anything special to ensure that the assignments to the Worker members are complete and will be visible to the new thread.
In general, you should never have to use a memory fence when writing multithreaded C++11: synchronization is built into mutexes/atomics and they handle any necessary fences for you. (Caveat: you are on your own if you use relaxed atomics.)
I wanted to use boost::thread in my program, but get the following compiler error (Visual Studio 2005):
Error 1 **error C2064**: term does not evaluate to a function taking 0
arguments d:\...\boost_1_37_0\boost\thread\detail\thread.hpp 56
Therefore I tried to recreate the problem in a small program and modified the working Hello World example from this site.
My test code now looks like this. Why is it not working inside a class?:
#include <boost/thread.hpp>
#include <iostream>
class HelloWorld
{
public:
void hello();
void entry();
};
void HelloWorld::entry()
{
boost::thread thrd(&HelloWorld::hello);
thrd.join();
}
void HelloWorld::hello()
{
std::cout << "Hello world, I'm a thread!" << std::endl;
}
int main(int argc, char* argv[])
{
HelloWorld *bla = new HelloWorld;
bla->entry();
return 0;
}
Try it like this - the boost::thread constructor is expecting a boost::function0 (which a function pointer is, but a member function pointer isn't, due to the this pointer).
void HelloWorld::entry()
{
boost::thread thrd(boost::bind(&HelloWorld::hello,this));
thrd.join();
}
Member functions have a this pointer as the first argument. Since there is a boost::thread constructor that accepts function arguments, you don't need to use boost::bind. This will also work:
void HelloWorld::entry()
{
boost::thread thrd(&HelloWorld::hello,this);
thrd.join();
}
If your function requires arguments, you can put them after the this pointer argument.
You are passing a member function to the thread object as the function to call when the thread starts. Since the thread doesn't have the object itself, it can't call the member function. You could make the hello function static, or look at the boost::bind library to send in the object.