Pass *this as argument to method invoked by thread - c++

I have a member function which I cannot unit test easily (it listens to sockets etc):
void MyClass::func()
{
listen();
send();
}
So I want to template it and then I can pass a mock object in my test:
template<class OBJECT>
void func(OBJECT& obj)
{
obj.listen();
obj.send();
}
and then I'd do:
func(*this);
The above compiles when I do a normal function call. However, when I spawn a thread and call it:
std::thread t1(&MyClass::func, this, *this);
I get compiler errors (see below) referring to decltype. Is there a way I can still achieve this?
/opt/gcc-8.2.0/lib/gcc/x86_64-unknown-linux/8.2.0/../../../../include/c++/8.2.0/thread:127:8: note: in instantiation of template class 'std::thread::_Invoker<std::tuple<void (MyClass::*)(MyClass &),
MyClass *, MyClass> >' requested here
__make_invoker(std::forward<_Callable>(__f),
However, the following works:
void MyClass::x()
{
func(*this);
}
std::thread t1(&MyClass::x, this);

There are two issue in your code:
First, you cannot pass function templates to the std::thread constructor. You must explicitly specify what specialisation of the function template to use, which in this case, would be &MyClass::func<MyClass>.
Second you are trying to pass a reference as an argument to the constructor of std::thread. When the std::thread constructor is called, the first argument is the function to run concurrently, and the others are the argument to the function. The other arguments are moved and then passed as argument to the function. This is fine if the argument is a pointer or a variable, but causes an issue if the function expects a non-const lvalue as an argument.
You can solve both issues by constructing std::thread with lambdas:
std::thread t1([=]{
this->func(*this);
});
Conversely, you could use std::ref, a reference wrapper, in the std::thread constructor, and explicitly specify the function template specialisation:
#include<functional>
std::thread t1(&MyClass::func<MyClass>, this, std::ref(*this));
Personally, I much prefer constructing std::threads with lambdas, as it is cleaner and less error prone.

Related

How to pass argument to std::bind to a function?

I have the following code which used std::bind :
EventListenerCustom* _createNewObjectlistener =
eventDispatcher->addCustomEventListener(Constants::MY_EVENT,
std::bind(&MyClass::MyFunction, this, std::placeholders::_1));
It seems I create many different kinds of object listeners, where the only difference is the event, and the function being called. If I wanted to encapsulate the above code into a function:
How would I pass MyClass::MyFunction as an argument to the function ?
What would the function signature and parameters look like ?
I imagine the function would look something like this:
EventListenerCustom* MyFunc(<What Goes Here> functionToBeBound,<What goes here> object,std::string EVENT){
EventListenerCustom* eventListener = eventDispatcher->addCustomEventListener(EVENT, std::bind(functionToBeBound, object, std::placeholders::_1));
return eventListener;
}
What should the function look like ? And How do I call it? What would the calling code look like?
EDIT: Concrete details:
I have many listener objects which are created in identical ways:
auto eventDispatcher = _dragNode->getEventDispatcher();
_createNewObjectlistener = eventDispatcher->addCustomEventListener(Constants::MY_EVENT, std::bind(&MyClass::myOtherFunction, this, std::placeholders::_1));
_moveNewObjectlistener = eventDispatcher->addCustomEventListener(Constants::MY_EVENT2 std::bind(&MyClass::myFunction, this, std::placeholders::_1));
Constants::MY_EVENT etc are just const char* .
The only difference is the Function being called, and the string constant used as an event name. How can I encapsulate this into a function ? I have tried John Zwinck's solution below, but for some reason I can't get it to compile because the compiler complains:
: No viable conversion from '__bind<void (*&)(cocos2d::EventCustom *), MyNameSpace::MyClass *, const std::__1::placeholders::__ph<1> &>' to 'const std::function<void (EventCustom *)>'
To make it simpler, create a typedef for a pointer to any member function in MyClass which has the appropriate signature:
typedef void (MyClass::*MyMemberFn)(int); // replace int and void as needed
Then:
EventListenerCustom* MyFunc(MyMemberFn functionToBeBound, MyClass* object, std::string EVENT){
return eventDispatcher->addCustomEventListener(EVENT, std::bind(functionToBeBound, object, std::placeholders::_1));
}
What you're really looking for is std::function. The documentation for such is here: https://en.cppreference.com/w/cpp/utility/functional/function
Their example is really good at explaining how it's used, but for your case (or related) try this:
std::function<void(int)> func1 = std::bind(MyClass::MyFunction, this, std::placeholders::_1));
What this will do is create an object which can be called, and the first argument is forwarded on to the first argument of the member function, both of which should be int type, and it returns nothing. You don't actually need address-of operator for the function name.
The cool part here is that the object returned by std::bind can be passed into the constructor of std::function and all its information is preserved. So when you need a concrete type that can be copied and all that cool stuff (passed into a function NOT by reference for example) then use a std::function as it will do the job, as long as it's not trying to copy a non-copyable type or something. std::function can also be initialized with a function pointer. It's generally just "better" than function pointers for C++, especially combined with std::bind to handle classes.
I could write out more examples, but check out the link above, and check out std::bind on that same website. Both should help.

Starting a thread or future with an std::string () const function [duplicate]

This question already has answers here:
Start thread with member function
(5 answers)
Closed 4 years ago.
I would like to spawn a thread or a future calling this function:
std::string myClass::myFunction() const noexcept
I first tried spawning them both like this:
thread t0(myFunction); auto f1 = async(myFunction);
I would then get this error:
no instance of constructor "std::thread::thread" matches the argument list. argument types are: (std::string () const)
I then read online that since it is const I would need to call it by reference but all methods online have not worked, I am unsure if the problem is because the function is const or not.
What I have tried:
thread t0(&myClass::myFunction); auto f1 = async(&myClass::myFunction);
and
thread t0(&myFunction); auto f1 = async(&myFunction);
After this I would have two new errors that I cannot find a solution to:
std::invoke: no matching overloaded function found.
and
Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)'
I think this is due to my lack of understand on how threads and futures work but I am struggling to find literature that gives me any relation to this.
Basically I don't really understand what rule I am breaking, if there is a fundamental flaw in my approach any direction or tips would be nice. Thank you for your time.
std::string myClass::myFunction() const noexcept
This is not a function. This is a class method. There is a fundamental different between the two.
You cannot simply write
myFunction();
Somewhere in your code, other than in another method of the same class, which uses this to invoke a different method for the same instance of the class. Anywhere outside a method of the same class, myFunction(); won't compile, and your compilation error is the same exact reason. The first parameter to std::thread's constructor is a function, not a class method. It can be a class method, which I'll get to shortly. But your first error is confusion between the concept of a function and a class method, that you need to understand.
You could make myFunction() a static class function, which then works just like any, ordinary, function, and then feed it to std::thread as usual. Another option is to construct std::thread using a wrapper function that passes whichever class whose method you wish to invoke to the wrapper function, and the wrapper function uses it. The "whichever class" could be this:
void invoke_func(const myClass *ptr)
{
ptr->myFunction();
}
// ...
std::thread new_thread{ this };
Another, a more modern approach that can be used to invoke a class method is to pass an additional parameter, a pointer to an instance of the class whose method you wish to invoke:
std::thread new_thread{ &myClass::myFunction, this };
The myFunction() method does not take any parameters here as arguments, but when the first parameter to std::thread's constructor is a class method, and not a function, the first parameter is taken to be a pointer to an instance of the class whose method gets invoked, with the remaining parameters getting forwarded as usual.
But you will need to figure out, on your own, which class's instance you are trying to invoke, whether this, or some other instance of your class.
Although you can often write foo() inside a class to invoke this->foo(), as a shortcut, this is not the case when you're outright "naming" the member function, and that's what you're doing here as you are actually passing a member function pointer to std::thread.
It can work, you just need to supply the object pointer too:
std::thread t0(myFunction, this);
You could pass a pointer to a different myClass instead, if you liked!

In C++, how do I add an argument to an "Args&&... args" list of arguments?

I have my own thread implementation which allows me to manage various ways of communicating with my threads. It is based on the C++ std::thread class.
I create the thread to run a function named run() which calls the user function. What I'd like to be able to do is call the user function including my thread object pointer.
There is where I have a problem in the constructor. I want to pass the Args as specified on the constructor and prepend this to that list:
class safe_thread
{
public:
typedef std::shared_ptr<safe_thread> pointer_t;
typedef std::vector<pointer_t> vector_t;
template<class Function, class... Args>
safe_thread(Function&& f, Args&&... args)
: f_function([this, f, args...]{ std::bind(f, this, args...)(); })
{
[...snip...]
private:
std::function<void()> f_function;
};
// I use that constructor with two different types of signatures:
//
// 1. member function
//
safe_thread listen(&my_other_class::some_function, this);
// 2. static function
//
safe_thread worker(&my_static_function);
std::bind() does not understand my current syntax. It expects a function (f) and args.... So, how do I change args... to include this?
For those interested, I actually found a solution which is to move the this parameter to the end of the list. This way my std::invoke() to a member function or a standard static function work alike:
f_function([this, f, args...]{ std::invoke(f, args..., this)(); })
Without that, as mentioned by Miles Budnek, a load of SFINAE would be required to know whether f is a member function or a plain function.
The problem was that in some cases I would create a thread in a member function and in other cases I would create a tread out of a static function.
In case of the member function, the first argument in the args... list is the caller's this and obviously that this can't be moved over as the next parameter.
In effect, my first attempt was generating this:
std::invoke(
&my_other_class::some_func, // correct
safe_thread::this, // wrong 'this' (i.e. safe_thread)
my_other_class::this, // 'this' for function, wrong location
...); // other parameters
By changing the order in my call, I now get the correct 'this' at the correct location:
std::invoke(
&my_other_class::some_func, // correct
my_other_class::this, // 'this' for function, correct location
..., // other parameters
safe_thread::this); // 'this' to safe_thread
Obviously this means I have to fix the signature of the called functions, but I'm fine with that.
As mentioned by tkausl, std::bind() is not required. See comments for details about that. That being said, std::invoke() is C++17, so if you're still on an older version, you'll probably have to stick to std::bind().

c++ call thread constructor

I was reading concurrency in action and came up with this piece of code. However, i dont quite understand why line<1> is syntax valid. Also, how the order got determined? is it possible to put std::thread t(&my_x, &X::do_lengthy_work); instead? how many inputs can take based on the code over here?
class X
{
public:
void do_lengthy_work();
};
X my_x;
std::thread t(&X::do_lengthy_work,&my_x); //<1> the bood says This code will invoke my_x.do_lengthy_work() on the new thread, because the address of my_x is supplied as the object pointer
I think that you are confused by the syntax here.
This is just a constructor call for an object of type std::thread named t (so the arguments order did not "get determined", it is defined by the constructor signature).
Two parameters are expected by this constructor :
1) A callable : &X::do_lengthy_work , as a pointer to a member function, is a Callable.
2) The arguments expected by the Callable : a member function always has an implicit this argument of type (const) X* : this is why here you pass &my_x, the address of the object on which the Callable will be called.
If you add an argument to do_lengthy_work, then you need to specify it when you construct the thread as well :
class X
{
public:
void do_lengthy_work(int i) {}
};
int main() {
X my_x;
std::thread t(&X::do_lengthy_work,&my_x, 2);
^^^^
}
Also, how the order got determined? is it possible to put std::thread
t(&my_x, &X::do_lengthy_work); instead?
As with any other c++ function order determined by function signature, in this case std::thread constructor signature:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
from std::thread documentation
As you can see that Function is the first parameter and parameters follow (if any). So you cannot put pointer to class before pointer to method.
Excellent book about the topic !
std::thread t(...); creates a thread object t. The first argument of the constructor must be either the adress of a function, or an executable class (i.e. a class with operator() defined).
For ordinary functions like void f(){... }, it would be sufficient to give its name as first argument f. For member function, you have to give its full name, so here: X::do_lengthy work. But for getting the pointer to the mbmer function an explicit & is required (see C++11 standard, section 5.3.1, pt 4).
The arguments following the first arguments will be given to the function when the thread starts and wants to execute it. In the specific case of member functions, the very first argument will be used to say on which object the function has to be executed.
So roughly speaking thread(&class::member_function, arg1, arg2, ... arg n) will call arg1.member_function (arg2, .... arg n).

Invoking a function from another class with Boost in c++

I am fairly new to both c++ and the boost library.
What I want to do is invoke a method foo from a class Bar inside a class Baz. Here is basically what I want to achieve:
Baz::doSomething() {
Bar bar;
boost::thread qux(bar.foo);
}
And the foo function could be something like:
// bar.cpp
void foo() {
const int leet = 1337; // Very useful
}
However, when I try to compile it tells me that:
error: no matching function for call to ‘boost::thread::thread(<unresolved overloaded function type>)’
/usr/local/include/boost/thread/detail/thread.hpp:215:9: note: candidates are: boost::thread::thread(boost::detail::thread_move_t<boost::thread>)
/usr/local/include/boost/thread/detail/thread.hpp:201:18: note: boost::thread::thread(F, typename boost::disable_if<boost::is_convertible<T&, boost::detail::thread_move_t<T> >, boost::thread::dummy*>::type) [with F = void (Snake::*)(), typename boost::disable_if<boost::is_convertible<T&, boost::detail::thread_move_t<T> >, boost::thread::dummy*>::type = boost::thread::dummy*]
/usr/local/include/boost/thread/detail/thread.hpp:154:9: note: boost::thread::thread()
/usr/local/include/boost/thread/detail/thread.hpp:122:18: note: boost::thread::thread(boost::detail::thread_data_ptr)
/usr/local/include/boost/thread/detail/thread.hpp:113:9: note: boost::thread::thread(boost::thread&)
What am I missing here?
Member functions are different from free functions.
You need to use std::mem_fun_ref to get a functor and boost::bind (or std::bind should your compiler support it) to bind the object on which the function should be called on to use them.
The end result should look something like this:
boost::thread qux(boost::bind(&Foo::bar, bar)); // makes a copy of bar
boost::thread qux(boost::bind(&Foo::bar, &bar)); // make no copy of bar and calls the original instance
Or don't use bind and let thread do the binding:
boost::thread qux(&Foo::bar, &bar);
Edit:
I remembered wrong: You don't need mem_fun, boost::bind supports pointers to members out of the box.
Thanks for the comments addressing the issue.
boost::thread qux(boost::bind(
&Bar::foo, // the method to invoke
&bar // the instance of the class
));