Can't start C++ std::thread with callable as argument - c++

I would like to have the following class setup in a program:
A class that implements a buffer. This buffer, when full, would spawn a thread that makes a callback to handle what to do with the full buffer.
A class that includes a buffer object. Implements the callback function.
I'm having some trouble spawning the std::thread that runs the callback. It seems like I'm getting its parameters wrong, but I can't figure it out.
The minimal reproducible example:
#include <thread>
class MyClass;
class CallbackClass
{
public:
void (MyClass::*callback)();
std::thread a_thread;
void setCallback(void (MyClass::*cb)())
{
callback = cb;
}
void writeCall()
{
a_thread = std::thread(callback); // error here
}
};
class MyClass
{
public:
CallbackClass callbackobject;
MyClass()
{
callbackobject.setCallback(&MyClass::bufferWriter);
}
void bufferWriter(){}
};
int main(){}
The compiler error I get:
error: no matching function for call to ‘std::thread::_Invoker<std::tuple<void (MyClass::*)()> >::_M_invoke(std::thread::_Invoker<std::tuple<void (MyClass::*)()> >::_Indices)’
operator()()
on this line:
a_thread = std::thread(callback); // error here

void (MyClass::*callback)();
This is a pointer to a class method.
a_thread = std::thread(callback);
A class method is not a function that can be called by itself. The class method requires an object for which it gets invoked. You need to store, or obtain a pointer to a MyClass object, from somewhere. For example, you can pass a 2nd parameter to `setCallback:
void setCallback(void (MyClass::*cb)(), MyClass *ptr)
and then stash it away, somewhere, then use it to invoke the class method. Typically, this would be something like:
a_thread = std::thread(callback, ptr);

Related

How to pass lambda function by pointer?

I am a new in c++ maybe I miss something, but actually what I need to do is: I have a class that processing something in other thread, during this processing I need that it invoke a callback for progress.
How I see I can do it, I need to declarate pointer (maybe shared_ptr) for my callback function as a class member, than I have a setter in order to pass pointer to callback and then I can use it. A few issues here are how to pass it correctly? How to invoke pointer on function?
My implementation is:
class RobocopyCopy
{
//Public members
public:
typedef std::function<void(int)> TVoidIntCallback;
RobocopyCopy * set_monitoring_done_callback(TVoidIntCallback monitoring_done_callback)
{
m_pMonitoring_done_callback = &monitoring_done_callback;
return this;
}
//This method executes in background
void execute()
{
...
//and here I need to invoke my callback
(TVoidIntCallback *)m_pMonitoring_done_callback(777); //but this is not correct
private:
TVoidIntCallback * m_pMonitoring_done_callback;
...
}
and final implementation of this should be like this (I think) :
RobocopyCopy robocopy;
robocopy.set_monitoring_done_callback([this](int my_progress) {
printf("Progress is :: %d", my_progress);
});
So, as I mentioned above questions is :
how to pass this function callback as a lambda and save in Robocopy class as a pointer
How to invoke this function correctly, because this (TVoidIntCallback *)m_pMonitoring_done_callback(777); doesn't work.
I am using VC++ I hope this code will be successful for you.
class RobocopyCopy
{
typedef std::function<void(int)> TVoidIntCallback;
TVoidIntCallback evnt;
public:
RobocopyCopy* set_monitoring_done_callback(TVoidIntCallback
monitoring_done_callback)
{
//set callBack function from out side.
evnt = monitoring_done_callback;
return this;
}
void execute() {
//invoke your callBack
evnt(1000000);
}
};
int main()
{
RobocopyCopy obj;
obj.set_monitoring_done_callback([](int data) {
std::cout << data << "\n";
})->execute();
}

Callback function C++

I'm having a great deal of problems trying to make a callback system. I want to pass a function to another class's function to receive data.
I want ExampleClass to call SeperateThread::operate, and I want SeperateThread::operate to be able to call ExampleClass::updateNumber(int) to return a value. I've been trying for hours with various function pointers etc but can't seem to get it to work.
SeperateThread is another thread so it doesn't block the main thread that ExampleClass is running in, but when SeperateThread has done it's calculations, I need to return the value to ExampleClass.
If that makes sense? Here's a run down of what I'm trying to do. In this example, I want SeperateThread::operate to call ExampleClass::updatenumber(15);...
class ExampleClass
{
public:
ExampleClass()
{
int numberToPass = 10;
// call SeperateThread::operate and pass value and updatenumber function as pointer
thread.operate(numberToPass, *updatenumber(int number));
}
~ExampleClass();
void updatenumber(int number)
{
// Do some stuff to the number passed to this function
}
private:
SeperateThread thread;
}
class SeperateThread
{
public:
SeperateThread();
~SeperateThread();
void operate(int number, &FunctionToCallBack)
{
// Do some calculations (result 5 for example purposes)
int result = numberToPass + 5;
// Call the callback function and pass result int
FunctionToCallBack(result);
}
}
There are two issues here:
1. A Callback Function Is Not Enough
You'll need both an address for the code to call back, and the identity of the object on which the code should operate. The idiomatic C++ way to do this is to encapsulate this in an object:
class SeparateThread {
public:
class Callback {
public:
virtual void ThreadDone(int result) const = 0;
virtual ~Callback() {}
};
void operate(int number, const Callback & callback)
{
// Calculate result
callback.ThreadDone(result);
}
};
ExampleClass can then either inherit privately from SeparateThread::Callback and implement ThreadDone() or define a separate callback class:
class ExampleClassThreadCallback : public SeparateThread::Callback {
public:
ExampleClassThreadCallback(ExampleClass * obj) : fObj(obj) {}
void ThreadDone(int result) const override {
fObj.updatenumber(result);
private:
ExampleClass * fObj;
}
};
You then simply call the thread as:
thread.operate(number, ExampleClassThreadCallback(this));
2. Concurrency
In a design like this, where your class gets updated from a separate thread, you are likely to run into concurrency issues, so you'll have to design appropriate mechanisms to make sure that this updating does not cause problems.
There is something important about pointing to a class member function, you have to keep in mind that a function pointer is just a regular pointer but instead of a value it points to a function, but in a class there is a special hidden variable this which makes it tricky.
One of the main problems here is that there is no pointer to the object since that would mean that you point to a function that exists within a specific object but it doesn't it just a plain function that contains this as a parameter.
thread.operate(numberToPass, *updatenumber(int number));
Here you call a function that is in another class and overall you never pass a pointer like this, it should be just the function's name since C will recognize that you want to pass it as a pointer. Generally the workaround would be to make the function static to avoid the problem with the this pointer.
One possible workaround would be to hold onto the class object and somehow hackishly call that function where you manually pass the this of the original object ( ExampleClass ).
You didn't say much about your design, but the fact that you put the source into the same field means that these classes "know" each other so why don't you just pass the class object and call the function that way like:
class BaseClass
{
public:
BaseClass() {}
~BaseClass() {}
virtual void updatenumber(int number)=0; // pure virutal method, you MUST implement this in the subclasses!
}
class ExampleClass : public BaseClass
{
public:
ExampleClass()
{
int numberToPass = 10;
// call SeperateThread::operate and pass value and updatenumber function as pointer
thread.operate(numberToPass, this);
}
~ExampleClass();
// this is now a virtual method
void updatenumber(int number)
{
// Do some stuff to the number passed to this function
}
private:
SeperateThread thread;
}
class SeperateThread
{
public:
SeperateThread();
~SeperateThread();
void operate(int number,BaseClass* ObjectToCallBack)
{
// Do some calculations (result 5 for example purposes)
int result = numberToPass + 5;
// Call the callback function and pass result int
// Note that here that this points to the BaseClass pointer but it can be a subclass of it effectively hiding it's "unneded members" at this specific point
ObjectToCallBack->updatenumber(result);
}
}
In case you want to hide the implementation you can just use a pure virtual class and pass that type of pointer to the SeperateThread class.
Edit : updated my example to use a base class.
There is a way to pass a member of a specific class instance to another function whether in a thread or not. If the callback is a member you need to wrap it together with the class instance you want the callback to affect.
template<typename T, typename F, typename R>
struct callback
{
callback(T cthis, F func) : _this(cthis), _func(func) { }
void operator()(R result)
{
(_this->*_func)(result);
}
T _this;
F _func;
};
class SeperateThread
{
public:
SeperateThread() { }
~SeperateThread() { }
template<typename T, typename F, typename R>
void operate(int number, callback<T,F,R> cb)
{
// Do some calculations (result 5 for example purposes)
int result = number + 5;
// Call the callback function and pass result int
cb(result);
}
};
class ExampleClass
{
public:
ExampleClass()
{
int numberToPass = 10;
// call SeperateThread::operate and pass value and updatenumber function as pointer
thread.operate(numberToPass, callback<ExampleClass * const, void (ExampleClass::*)(int), int>(this, &ExampleClass::updatenumber) );
}
~ExampleClass() { }
void updatenumber(int number)
{
// Do some stuff to the number passed to this function
printf("Result is %d\n", number);
}
private:
SeperateThread thread;
};
void test()
{
ExampleClass a;
}
The above will print: Result is 15.
Please note that I did not address the synchronization issues due to multithreading.
If 'updatenumber' is called by more than one thread, and your code inside it accesses other data members, then you need to serialize it by adding a mutex lock at the beginning and unlock it before returning. Best is to use std::mutex if you have C++11 compiler, or do this within a small struct, locking in the constructor and unlocking in the destructor. Then you just create one such instance immediately on updatenumber() entry.

How to make a method call another method in the same class in a new thread?

I need to make a method in a class call another method in the same class in a new thread but am having some trouble. I get the compile error: " 'this' is unavailable for static member functions". I made an example of my issue since I can't post the raw code here.
Basically, what happens is I make an object of my class (known as aClass in the below example) then I call a method such as do_stuff(). The do_stuff() method uses pthread_create to call the print_number() method in a new thread. The problem is, when I go to compile I get an error saying that I can't use this because my print_number() method is static. If I don't make the print_number() method static, then pthread_create complains that its not a compatible type.
I understand why I wouldn't be able to use this inside the print_number() method itself since it's static and can then be called with no object. However, in my print_number() method, I'm not using this. I'm using the pointer to the object I created. In do_stuff() I use this to pass a reference to the object I created to print_number but I don't use this in print_number itself. So I'm not understanding what the issue is. Thanks for the help!
class aClass
{
private:
number;
public:
void do_stuff(void);
static void* print_number(void* arg)
}
// this method is called first
void aClass::do_stuff()
{
number = 4;
pthread_t thread1;
pthread_create( &thread1, NULL, print_number, this);
.....
}
//this method is called from the do_stuff() method in a new thread
void* aClass::print_number(void* arg)
{
aClass* objPTR = (aClass*)arg;
printf("number = %d", objPTR->number);
}
//don't get caught up here.. the point is that an object is created and
// the "do_stuff()" method is called
int main()
{
//all the usual stuff here
aClass someObject;
someObject.do_stuff();
}
U need to make the print_number declaration static inside the class.
Just replace the line
class aClass
{
private:
number;
public:
void do_stuff(void);
void* print_number(void* arg)
};
with the below code
class aClass
{
private:
int number;
public:
void do_stuff(void);
static void* print_number(void* arg);
};
This is just the class part only.
Compile it hope it will solve your problem.

Most general way to receive a functor as a parameter?

I am writing a wrapper for a multithreaded scheme. It should operate similar to a timer.
I have a particular class (clock) that implements a function called tick which should be passed to constructor. How do I describe a C++ style function (myClass::myfunction, as opposed to the C convention) as the parameter to a method or constructor?
Would anybody be kind enough to show me the declaration for this kind of constructor?
clock myInstance(otherClass::aMethod)
myInstance.tick(); // Should call otherClass::aMethod
myInstance.tick();
Does C++11 and Bind help?
You can either call a static member function of a class or a non-static member function of an object. A non-static member function needs to have the context of an object (this pointer).
Here's a simplified example of how you can use functors and bind to call a member function.
#include <functional>
class clock
{
public:
clock(const std::function<void()>& tocall) : m_tocall(tocall) {}
void tick() {m_tocall();}
private:
std::function<void()> m_tocall;
};
class otherclass
{
public:
void aMethod() {}
};
int main(int argc, char *argv[])
{
otherclass A;
clock c( std::bind(&otherclass::aMethod, &A) );
c.tick(); // Will end up calling aMethod() of object A
}
You need not to use std::function for this. You need to have TWO pointers: One is the class-object, and one to the method of that class. In simple terms, you need to make it able to do:
CallNonVirtual(pClassPtr, pFuncAddr);
And therefore, you need both parameters, so that you can actually call it like:
(pClassPtr->*pFuncAddr)(); // Assuming no parameter
For this, you can do:
class Clock
{
COtherClass* pClassPtr;
/// Typedef simplifies
typedef void (COtherClass::*TargetFuncType)();
TargetFuncType pFuncAddr;
public:
Clock(COtherClass* pOther, TargetFuncType pFunc) :
pClassPtr(pOther), pFuncAddr(pFunc)
{
}
void tick()
{
(pClassPtr->*pFuncAddr)();
}
};
And make a call:
int main()
{
COtherClass Obj;
Clock theClock(&Obj, &COtherClass::TheNonStatic);
theClock.tick();
}

How to pass a method as callback to another class?

I have a question regarding callbacks using tr1::function. I've defined the following:
class SomeClass {
public:
typedef std::tr1::function<void(unsigned char*, int)> Callback;
void registerCallback(Callback);
private:
Callback callback;
}
I've defined another class:
class SomeOtherClass {
void myCallback(unsigned char*, int);
}
Now I want to register my function 'myCallback' as callback at class 'SomeClass'using the method 'registerCallback'. However, it is not working. I've had a look on the boost documentation on the function and it seems legit to use (member) methods of a class for callbacks. Am I wrong?
Thanks in advance!
Member functions have an implicit first parameter, a this pointer so as to know which object to call the function on. Normally, it's hidden from you, but to bind a member function to std::function, you need to explicitly provide the class type in template parameter.
#include <functional>
#include <iostream>
struct Callback_t {
void myCallback(int)
{
std::cout << "You called me?";
}
};
class SomeClass {
public:
SomeClass() : callback() { }
typedef std::function<void(Callback_t*, int)> Callback;
// ^^^^^^^^^^^
void registerCallback(const Callback& c)
{
callback = c;
}
void callOn(Callback_t* p)
{
callback(p, 42);
}
private:
Callback callback;
};
int main()
{
SomeClass sc;
sc.registerCallback(&Callback_t::myCallback);
Callback_t cb; // we need an instance of Callback_t to call a member on
sc.callOn(&cb);
}
Output: You called me?;
Why all this complicated mumbo-jumbo?
Why not create a class as thus (for example)
Class MouseOverEventCallBack
{
public:
virtual void RunMouseOverCallback() = 0;
};
Then just create classes that inherit this class (and redefine the method RunMouseOverCallback)
Then Register function just needs to be
void registerCallback(MouseOverEventCallBack *callbackObject); // possible could use a reference
The register method will just call the method and the object will have all that it needs.
Seems a bit simpler. Let the compiler do the work with pointers to functions etc.
the function void (*)(unsigned char*, int) is a free function, which is a different type from void (SomeOtherClass::*)(unsigned char*, int), thus the error. You need an object to call the latter, while the former is a free function.
Look at the possible solutions listed in the Boost documentation
Another possibility is that your SomeOtherClass::myCallback is private, so you do not have access to it.
Use templates:
template <class T>
class B
{
public:
typedef void (T::*TCallBackFunction)(void);
void SetCallBack(T* pCallBackClass, TCallBackFunction pCallBackFunction)
{
if(pCallBackFunction && pCallBackClass)
{
m_pCallBackFunction = pCallBackFunction;
m_pCallBackClass = pCallBackClass;
}
}
void StartCallBackFunction()
{
(pCallBackClass->(*m_pCallBackFunction))();
}
private:
TCallBackFunction m_pCallBackFunction;
T* m_pCallBackClass;
};
Such like this. And use it:
...
B<MyClass> b;
b.SetCallBack(&b, &MyClass::MyFunction);
...