I am a little confused on how pthread works - specifically, I am pretty sure that pthread takes in a pointer to a function that takes a void pointer as an argument (correct me if I am wrong), and I have declared my function in that way, but I am still getting an error. Here is the code I am struggling with:
void eva::OSDAccessibility::_resumeWrapper(void* x)
{
logdbg("Starting Connection.");
_listener->resume();
logdbg("Connected.");
pthread_exit(NULL);
}
void eva::OSDAccessibility::resumeConnection()
{
long t;
_listener->setDelegate(_TD);
pthread_t threads[1];
pthread_create(&threads[0], NULL, &eva::OSDAccessibility::_resumeWrapper, (void *)t);
}
The error I'm getting is:
No matching function for call to pthread_create.
You don't necessarily have to tell me how to fix the code (although that would be appreciated of course), I'm more interested in why this error is coming up and if my understanding of pthread is correct. Thanks! :)
Your function signature must be void * function (void*)
If called from c++ code, the method must be static:
class myClass
{
public:
static void * function(void *);
}
A solution to use methods that are not static is the following:
class myClass
{
// the interesting function that is not an acceptable parameter of pthread_create
void * function();
public:
// the thread entry point
static void * functionEntryPoint(void *p)
{
((myClass*)p)->function();
}
}
And to launch the thread:
myClass *p = ...;
pthread_create(&tid, NULL, myClass::functionEntryPoint, p);
Related
So I started to develope an OpenCV program and the thing is that I don't know what this segment of code do in the whole context. Below is an abstract version of the whole code.
class foo{
private:
friend void callBack(void *param);
void draw(void);
public:
void func(void);
void update(void);
}
void callBack(void *param){
foo *context = static_cast<foo*>(param);
if(context){
context->draw();
}
}
foo::foo(std::string windowName){
cv::namedWindow(windowName, frameSize.width, frameSize.height);
cv::resizeWindow(windowName, frameSize.width, frameSize.height);
cv::setOpenGlContext(windowName);
cv::setOpenGlDrawCallback(windowName, callBack, this);
}
void foo::func(void){
cv::updateWindow(m_windowName);
}
void draw(void){
//implementation shows here!!
}
You don't have to explain all the code here. All I need to know is the part where static casting happens. What does it do? Why does a person who implements the code write it this way?
As you can see from the documentation of cv::setOpenGlDrawCallback
The signature is:
void cv::setOpenGlDrawCallback(const String& winname,
OpenGlDrawCallback onOpenGlDraw,
void* userdata = 0
)
The OpenGLDrawCallback is a function pointer of type void (void* arg): where arg is any pointer type you pass to it. In this case, OpenCV actually passes userdata to it. See How do function pointers in C work? (still applicable to C++)
cv::setOpenGlDrawCallback(windowName, callBack, this);
In your code, passing this implicitly converted (a copy of the pointer) it to void* and held by userdata . And and callback is called to draw on your frame
All I need to know is the part where static casting happens. What does
it do? Why does a person who implements the code write it this way?
void callBack(void *param){
foo *context = static_cast<foo*>(param);
if(context){
context->draw();
}
}
The casting converts the void pointer, param to an object of type foo. it basically gets back the semantics of this that was casted when you passed it as a void pointer.
I have the following encapsulation for my pthread_t threads:
#include <pthread.h>
class Thread
{
public:
void run(const int);
static void *run_helper(void *);
bool startThread(int);
void joinThread();
pthread_t th;
};
Where run is my thread routine, and run_helper is the following:
void *Thread::run_helper(int num)
{
return (Thread *)this->run(num);
}
I start my threads like such:
bool Thread::startThread(intptr_t arg)
{
return (pthread_create(&this->th, NULL, &run_helper(arg), (void *)(intptr_t)arg));
}
But when I compile, I get the following errors:
error: lvalue required as unary ‘&’ operand
return (pthread_create(&this->th, NULL, &run_helper(arg), (void *)(intptr_t)arg));
error: ‘this’ is unavailable for static member functions
return (Thread *)this->run(num);
And despite trying, I can't seem to make this encapsulation work.
I think your issue might specifically be &this->th. & has higher precedence than ->. Perhaps try &(this->th).
For the first error, you need to cast the third argument into (void*(*)(void*)) and remove & (maybe the casting isn't neccessary).
pthread_create(&this->th, NULL, (void*(*)(void*))run_helper(arg), (void *)(intptr_t)arg);
The second error, you are trying to use pointer to this in a static function, but the function isn't called on any object, therefore you can't use this in a function like that. The solution is to cast arg into Thread* and then call the non-static run function.
I'm doing to implement thread class for my own using pthread. So, I create Thread class as below :
class Thread
{
public:
Thread()
{
}
virtual void* run(void *params) = 0;
void start(void *params)
{
pthread_create (&threadId, 0, run, params);
pthread_join (threadId, 0);
}
private:
pthread_t threadId;
};
After implementing this class and override virtual run function, I do compile this project. But error: argument of type ‘void* (Thread::)(void*)’ does not match ‘void* (*)(void*)’ occurs. What is wrong in my code?
Thanks in advance :)
Exactly what the compiler is telling you.
pthread_create is expecting a function with the signature :
void* (*)(void*)
Which is a function pointer.
However, you are providing something with this signature:
void* (Thread::)(void*)
Which is not a function pointer, but a pointer to member function. There is a difference : a pointer to member function needs an instance of an object in order to work properly (here, it would need an instance of Thread).
A usual solution would be to make your function run static : it would not be a member function anymore - it doesn't NEED an instance of Thread in order to work properly anymore, and you could pass your current instance as the last parameter of pthread_create in order to act on it once the thread is launched.
You would just need to save the parameters in the class itself.
public:
void start(void *params)
{
this->my_thread_params = params;
pthread_create (&threadId, 0, run, static_cast<void*>(this));
}
private:
static void *run(void *my_object)
{
// here, my_object already contains the params you passed to the function start
static_cast<Thread*>(my_object)->my_member_function();
}
pthread_create is a C function, and knows nothing of C++ member functions. You'll need to give it a static or non-member function, and pass a pointer to your Thread object via the final argument of pthread_create; something like:
class Thread
{
virtual void* run(void *params) = 0;
void start(void * params)
{
this->params = params;
pthread_create(&threadId, 0, &Thread::static_run, this);
}
static void * static_run(void * void_this)
{
Thread * thread_this = static_cast<Thread*>(void_this);
return thread_this->run(thread_this->params);
}
private:
pthread_t threadId;
void *params;
};
Of course in modern C++, this is rather more straightforward:
std::thread thread;
void start(void * params)
{
thread = std::thread([this]{run(params);});
}
(Although of course you shouldn't be using void* to pass your parameters, and there's probably no good reason to wrap the thread up in a class in the first place.)
The error message is telling you that a pointer to a member function in Thread that takes and returns a void* (void* (Thread::*)(void*)) is not convertible to a pointer to function taking and returning the same void*.
While the declaration of the member function may look similar to the type that you need, there is an implicit this pointer of type Thread that needs to be injected on any call to Thread::run
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
pthread Function from a Class
I have this code that I can't get to compile because of the pthread_create line:
void* gtk_functor::_threaded_run(void* win)
{
Gtk::Window* w = static_cast<Gtk::Window*>(win);
Gtk::Main::run(*w);
delete w;
}
void gtk_functor::operator ()(Gtk::Window& win, bool threaded)
{
if (threaded)
{
pthread_t t_num;
pthread_create(&t_num, NULL, (void* (*)(void*))>k_functor::_threaded_run, static_cast<void*>(&win));
}
else
{
Gtk::Main::run(win);
}
}
This gcc line:
g++ -o main 'pkg-config --cflags --libs sqlite3 gtkmm-3.0' -lpthread main.cpp
does in the end compile with this output:
code/ui.cpp: In member function 'void ui::gtk_functor::operator()(Gtk::Window&, bool)':
code/ui.cpp:45:65: warning: converting from 'void* (ui::gtk_functor::*)(void*)' to 'void* (*)(void*)' [-Wpmf-conversions]
and apparently the code doesn't work correctly, I get sementation fault when the if (threaded) is raised.
I know its with the cast, but I don't know the correct form of passing a member function into pthread_create. Any suggestions?
Try making _threaded_run static. In the header:
private:
static void* _threaded_run(void*);
And in the implementation:
void* gtk_functor::_threaded_run(void* win) {
Gtk::Window* w = static_cast<Gtk::Window*>(win);
Gtk::Main::run(*w);
delete w;
}
Then when creating the thread:
pthread_create(&t_num, NULL, >k_functor::_threaded_run, static_cast<void*>(&win));
As #ildjarn suggests, just make a free function:
void * threaded_run(void * win)
{
Gtk::Window * const w = static_cast<Gtk::Window*>(win);
Gtk::Main::run(*w);
delete w;
}
// ...
pthread_create(&t_num, NULL, threaded_run, &win);
Since the function does not depend on the state of any particular gtk_functor object, there is no point in making it a member function.
In a hypothetical different world where you really would want an object's member function to be called in a separate thread, you need to pass the object reference for the object around somehow, usually via the argument void pointer:
struct Foo
{
void * run() { /* ... use state ... */ }
/* ... state ... */
};
Foo x;
pthread_t pt;
// start a new execution context with x.run():
pthread_create(&pt, NULL, FooInvoker, &x);
extern "C" void * FooInvoker(void * p)
{
return static_cast<Foo*>(p)->run();
}
In fact, you may even wish to package up more contextual information into some auxiliary structure and pass a void pointer to that to the thread invoker function.
I'm working on the open project gridlabd hosted at sourceforge. I was trying to call the create_thread function: static __inline int create_thread(void * (*proc)(void *), void *arg)
I just don't understand for the life of me what in the world void * (*proc)(void *) means.
void * (*proc)(void *) is a pointer to a function which returns void* and accepts void* as an argument.
It's a pointer to a function, said function taking a void pointer as an argument and returning a void pointer.
In other words, you can do:
void *threadMain (void *arg) { while (1) doSomething(); }
int stat = create_thread (threadMain, NULL);
to create a thread using the function threadMain as it's procedure.