How to multithreading a class member function with pthreads? - c++

I'm trying to run a function named extensionStep from a class named SVAnchor in multi threads. i use this code:
rc = pthread_create(&threads[i], NULL, extensionStep, &td[i]);
to call the function and here is the definition of extensionStep :
void* SVAnchor::extensionStep( void *threadarg)
and i got the following error:
error: cannot convert 'SVAnchor::extensionStep' from type 'void* (SVAnchor::)(void*)' to type 'void* (*)(void*)'
rc = pthread_create(&threads[i], NULL, extensionStep, &td[i]);
^
that shows the problem is converting from type 'void* (SVAnchor::)(void*)' to type 'void* ()(void)'
How to solve this problem?
Thanks all

This should do the job: (After making the function extensionStep static)
rc = pthread_create(&threads[i], NULL, &(SVAnchor::extensionStep), &td[i]);
Or you can create a wrapper function like this:
struct Argument {
SVAnchor* ptr;
int* tid;
}
static void *extensionStepWrapper(void *arg)
{
return (((Argument*)arg)->ptr)->extensionStep(((Argument*)arg)->tid);
}
And use the wrapper:
Argument arg;
arg.ptr = &(class_variable_name); // Use appropriate name (whatever you variable name is for the object of the class SVAnchor)
arg.tid = &(td[i]);
rc = pthread_create(&threads[i], NULL, &(SVAnchor::extensionStepWrapper), &arg);
Note that if you're calling this from inside another member function, you may do this instead:
arg.ptr = this;
You can also create a method in the class to start the thread:
bool StartThread(int* tid){
return (pthread_create(&_thread, NULL, extensionStep, tid) == 0);
}
You might also need to pass the thread as argument of StartThread() function.

This is a common mapping of a class member function to a C-callback:
#include <iostream>
#include <pthread.h>
class Task
{
public:
Task() : thread_id(0) {}
bool start() {
// Passing this as user data to the C-callback.
return pthread_create(&thread_id, 0, invoke, this) == 0;
}
void stop() {
void* no_result;
pthread_join(thread_id, &no_result);
}
private:
Task(const Task&); // no copy (C++11 delete)
Task& operator = (const Task&); // no copy (C++11 delete)
void process() {
std::cout << "Hello\n";
}
// The C-callback has to be static.
static void* invoke(void* self) {
// Note: The invocation takes place in start (passing this)
static_cast<Task*>(self)->process();
// No result passed to join.
return 0;
}
pthread_t thread_id;
};
int main() {
Task task;
task.start();
task.stop();
}
This is a C++11 version:
#include <iostream>
#include <thread>
class Task
{
public:
void operator () () {
std::cout << "Hello\n";
}
};
int main() {
Task task;
std::thread thread(task);
thread.join();
}

Related

Why can't I kill pthread via class object argument passed in

I initiate a background thread to run my class function, the task is executed as an infinite loop until client side decide to stop. So since when create pthread the class object 'this' is passed into thread, I tried to cast it to class object but get a null object, can anyone explain to me why this is not workable ?
void Camera::init()
{
typedef void *(*ThreadFuncPtr)(void *);
this->quit=false;
pthread_create(&acq, NULL, (ThreadFuncPtr)(&Camera::_acquireImages), this);
}
void Camera::stopAcquire()
{
this->quit=true;
}
void Camera::_acquireImages(void* ptr)
{
auto obj = (Camera*) ptr; //obj after cast shows as NULL object
while(!obj->quit){
//do something
}
pthread_exit(NULL);
}
So since when create pthread the class object 'this' is passed into
thread
pthread_create is a C function and expects the function signature to be void* (*)(void*) but it now has the signature void (Camera::*)(void*) so there are two errors: The function should return void* and it's also a non-static class member. To fix it, make the function return void* and make it static:
void Camera::init()
{
this->quit = false;
// now that the function has the correct signature, you don't need
// to cast it (into something that it wasn't)
pthread_create(&acq, NULL, &Camera::acquireImages, this);
}
void Camera::stopAcquire()
{
this->quit = true;
}
/*static*/ void* Camera::acquiredImages(void* ptr) // make it static in the declaration
{
Camera& obj = *static_cast<Camera*>(ptr);
while(obj.quit == false){
//do something
}
return nullptr;
}
If you are using C++11 (or newer), you should however take a look at the standard <thread> which makes life much easier.
#include <thread>
struct Camera {
void init() {
quit = false;
th = std::thread(&Camera::acquireImages, this);
}
~Camera() {
stopAcquire();
}
void acquireImages() {
// no need for casting. "this" points at the object which started the thread
while(quit == false) {
std::cout << ".";
}
}
void stopAcquire() {
if(th.joinable()) {
quit = true;
th.join(); // hang here until the thread is done
}
}
std::thread th{};
bool quit = false;
};

c++. function pointer to template function produces unresolved overloaded function type error

I need to make a class method take a template function as a pointer to function parameter, and then call it.
But I am running into
ThreadPool.hh:55:2: error: no matching function for call to ‘ThreadPoolElem<int>::start(<unresolved overloaded function type>, ThreadPoolElem<int>*)’
Samples and explanation of my code are :
I have a main module ThreadPool, which have a vector of ThreadPoolElem. As you may have guessed ThreadPoolElem are an encapsulation of Threads and ThreadPool plays the thread pool manager role. From ThreadPool I need to iterate the threadPoolElem vector. For each element in the vector I need to call its 'start' member function which take 2 argumens (the first one being a pointer to function). In the 'start' member function of The ThreadPoolElem class it uses the first argument as the callback for the third pthread_create c library function.
my threadpool file goest like this :
template <typename T>
class ThreadPool
{
Mutex _mutex;
CondVar _condVar;
SafeQueue<T> _tasks;
std::vector<ThreadPoolElem<T> > _threadVector;
/* .... */
void run(void)
{
for (typename std::vector<ThreadPoolElem<T> >::iterator it = this>_threadVector.begin();
it != this->_threadVector.end();
++it)
{
it->start(run_tramp, &(*it));
}
}
My ThreadPoolElem file goes like this:
template <typename T>
class ThreadPoolElem : public ThreadT<T>
{
SafeQueue<T> *_tasks;
CondVar *_condVar;
Mutex *_mutex;
public:
ThreadPoolElem(void) {}
void init(SafeQueue<T> *queue, CondVar *condVar, Mutex *mutex){
this->_mutex = mutex;
this->_condVar = condVar;
this->_tasks = queue;
}
void run(void){
while (true)
{
this->_mutex.lock();
if (this->_tasks.empty())
{
this->_condVar->wait();
this->_mutex->unlock();
}
else
{
int value;
this->_tasks->tryPop(&value);
std::cout << "consuming value" << std::endl;
if (!this->_tasks->empty())
{
this->_mutex->unlock();
this->_condVar->signal();
}
else
this->_mutex->unlock();
}
}
}
};
This is c like function (trampoline function) i need to take as a ptr to function parameter
template <typename T>
void *run_tramp(void *data)
{
reinterpret_cast<ThreadPoolElem<T> *>(data)->run();
return NULL;
}
And the final relevant file is :
template <typename T>
class ThreadT
{
public:
typedef enum
{
NOT_YET_STARTED,
RUNNING,
DEAD,
}thread_status;
private:
thread_status status_;
pthread_t thread_;
public:
/* .... */
void start(void *(*ptr)(void *), void* data){
this->status_ = RUNNING;
if (pthread_create(&this->thread_, NULL, ptr, data) != 0)
throw (SystemError("pthread_create"));
}
/* ...... */
};
You aren't using a templated function instantiation when you pass the pointer to your 'trampoline function' to the ThreadT<T>::start() method, you'll need to specify for which T it should be instantiated:
it->start(run_tramp<T>, &(*it));
// ^^^

Generalizing C++11 Threads class to work with lambda

I have a simple Threads class based on pthreads which works fine with a standard static callback function.
Is it possible to generalize Threads to work with lambdas, too?
problems:
sandbox.cpp:27:26: error: invalid cast from type ‘main(int, char*)::’ to type ‘void’
thread_cb() needs to deal with generically casting void* back into something callable
I suspect the second problem may be solved with template methods or maybe std::function, but not sure how.
#include <vector>
#include <iostream>
#include <pthread.h>
class Threads
{
public:
Threads() { }
~Threads() { }
private:
static void *thread_cb( void *v )
{
// following will also need to change
void (*my_fptr)() =
reinterpret_cast<void(*)()>(reinterpret_cast<long long>(v));
my_fptr();
return nullptr;
}
public:
template<typename CALLBACK>
void spawn( CALLBACK cb )
{
pthread_t t;
void *p = (void*)( cb ); // problem here
pthread_create( &t, nullptr, thread_cb, p );
m_threads.push_back( t );
}
void join_all()
{
for ( auto& p : m_threads )
pthread_join( p, nullptr );
}
private:
std::vector< pthread_t > m_threads;
};
static void my_cb()
{
std::cerr << "bar" << std::endl;
}
int main(int argc, char** argv)
{
Threads t;
t.spawn( my_cb ); // ok
t.spawn( []() { std::cerr << "foo" << std::endl; } ); // not ok
t.join_all();
return 0;
}
You can use "lambda to function pointer" conversion. ...be that as it may, I strongly recommend std::thread.
template<typename CALLBACK>
void spawn( CALLBACK cb )
{
pthread_t t;
// void *p = (void*)( cb );
// pthread_create( &t, nullptr, thread_cb, p );
void (*pfn)() = cb; // function pointer to `void()`
pthread_create( &t, nullptr, thread_cb, reinterpret_cast<void*>(pfn) );
m_threads.push_back( t );
}

Calling pthread_create inside a member function?

I created a widget.h file containing the declartions of pthread_function and I wanted to call it in a member function destroyWidget of that class Widget in widget.cpp. but always shows an error. I'll show the .cpp and .h file.
widget.h file
class Widget
{
public:
Widget();
void createWidget(int x,int y,int w,int h);
void showWidget();
int wid;
pthread_t thread;
int *incomingval,id;
void join();
Window win;
XEvent evt;
private:
void* destroyWidget(void* ptr);
Display *disp;
int screenNumber;
unsigned long white;
unsigned long black;
long eventMask;
GC gc;
int tbit;
int *incoming,val;
};
now the widget.cpp
Widget::Widget()
{
disp=XOpenDisplay( NULL );
screenNumber=DefaultScreen(disp);
white=WhitePixel(disp,screenNumber);
black=BlackPixel(disp,screenNumber);
eventMask=StructureNotifyMask;
tbit=0;
}
void Widget::createWidget(int x,int y,int w,int h)
{
wid=w;
win= XCreateSimpleWindow(disp,DefaultRootWindow(disp),x,y,w,h,1,white,black);
}
void Widget::showWidget()
{
XMapWindow(disp,win);
XFlush(disp);
gc=XCreateGC(disp,win,0,NULL);
XSetForeground(disp,gc,white);
XDrawLine(disp,win,gc,wid-10,0,wid,10);
XDrawLine(disp,win,gc,wid-10,10,wid,0);
//calling the thread function
pthread_create( &thread, NULL, destroyWidget, this);
}
void Widget::join()
{
pthread_join( thread, NULL);
}
void* Widget::destroyWidget(void* ptr)
{
Widget* mw = static_cast(ptr);
eventMask=ButtonPressMask|ButtonReleaseMask;
XSelectInput(disp,win,eventMask);
do{
printf("id= %d",id);
XNextEvent(disp,&evt);
}while(evt.type!=ButtonRelease);
XDestroyWindow(disp,win);
XCloseDisplay(disp);
return NULL;
}
now the main.cpp file
#include "widget.h"
#include
int main()
{
Widget* w=new Widget();
Widget* n=new Widget();
n->createWidget(20,20,150,150);
w->createWidget(50,50,250,250);
n->showWidget();
w->showWidget();
n->join();
w->join();
return 0;
}
the error is
widget.cpp: In member function ‘void Widget::showWidget()’:
widget.cpp:44:51: error: argument of type ‘void* (Widget::)(void*)’ does not match ‘void* (*)(void*)’
The problem is that pthread_create is a C-style function; you need to give it a pointer-to-function. Widget::destroyWidget() is a pointer-to-member-function. (Remember that non-static member functions always have an implied this argument, which pthread_create doesn't know how to provide.)
See the answers to this question for some possible solutions: pthread function from a class.
The third argument to pthread_create has the signature (in C++):
extern "C" void* (*pointerToFunction)( void* );
You're trying to pass it the address of a member function:
void* (Widget::*pointerToMemberFunction)( void* );
The signatures are incompatible: the second requires an object on which
to call it, and is not extern "C".
The simplest way of handling this is to use boost::thread, with all
it's functional object support. Otherwise, you can define something
like the following:
struct AbstractTask
{
virtual ~AbstractTask() {}
virtual void* run() = 0;
};
template<typename T, void* (T::*ptr)()>
class Task
{
T* myObject;
public:
Task( T* object ) : myObject( object ) {}
virtual void* run()
{
return (myObject->*ptr)();
}
};
extern "C" void* taskRunner( void* arg )
{
std::auto_ptr<AbstractTask> p( static_cast<AbstractTask*>( arg ) );
return p->run();
}
pthread_t taskStarter( AbstractTask* obj )
{
pthread_t result;
pthread_create( &result, NULL, &taskRunner, obj );
return result;
}
To start a thread, you then call:
thread = taskStarter( new Task<Widget, &Widget::destroyWidget>( this ) );
(This is from memory, from an earlier project, so there might be some
typos in it, but you get the idea. And you probably want to add some
error handling in taskStarter.)
Like Oli said you can't use a member function when a C-style function expects a "normal" function pointer. However, what you can do is make a separate function that calls back your destroyWidget() method.
Like so:
void* start_routine(void* arg)
{
Widget* widget = static_cast<Widget* >(arg);
widget->destroyWidget();
return NULL;
}
void Widget::showWidget()
{
pthread_create(&thread, NULL, &start_routine, this);
}
void Widget::destroyWidget()
{
// your code
}

C++ Class member callback

I have an error compiling this code:
template <class T> class purple_multitimer {
public:
typedef struct _timerinfo timerinfo, *ptimerinfo;
typedef gboolean (T::*multitimer_callback) (ptimerinfo pti);
typedef struct _timerinfo {
guint id;
multitimer_callback cb;
T * pthis;
purple_multitimer<T> * pmt;
} timerinfo, *ptimerinfo;
purple_multitimer() {
memset(m_ti, 0, sizeof(m_ti));
}
~purple_multitimer() {
stop();
}
void start(multitimer_callback mt_cb, T * pthis, guint timeout = 10) {
ptimerinfo pti = ti_get();
assert(pti);
pti->pthis = pthis;
pti->pmt = this;
pti->cb = mt_cb;
pti->id = purple_timeout_add_seconds(timeout, GSourceFunc(timeout_cb), pti);
}
void stop(multitimer_callback mt_cb = NULL) {
for (register guint n = 0; n < sizeof(m_ti)/sizeof(timerinfo); ++ n)
if (m_ti[n].cb == mt_cb) {
purple_timeout_remove(m_ti[n].id);
ti_zero(n);
}
}
private:
timerinfo m_ti[32];
inline ptimerinfo ti_get(guint n) {
return &m_ti[n];
}
inline ptimerinfo ti_get() {
for (register guint n = 0; n < sizeof(m_ti)/sizeof(timerinfo); ++ n)
if (m_ti[n].id == 0) return &m_ti[n];
return NULL;
}
inline ptimerinfo ti_zero(ptimerinfo pti) {
memset(pti, 0, sizeof(timerinfo));
return pti;
}
inline ptimerinfo ti_zero(guint n) {
memset(&m_ti[n], 0, sizeof(timerinfo));
return &m_ti[n];
}
static gboolean timeout_cb(ptimerinfo pti) {
gboolean res = (pti->pthis->*(pti->cb))(pti);
if (!res) pti->pmt->stop(pti->cb);
return res;
}
};
class _ctrl {
public:
purple_multitimer<_ctrl> pmt;
gboolean on_tomeout (purple_multitimer<_ctrl>::ptimerinfo pti) {
return false;
};
void on_connected(PurpleConnection *gc) {
pmt.start(purple_multitimer<_ctrl>::multitimer_callback(&_ctrl::on_tomeout), this);
}
void on_disconnected(PurpleConnection *gc) {
}
} controller;
When compiling this code got error:
[Error] E:\dnc-imexchange\dnc-imexchange.cpp:117: error: no matching function for call to `purple_multitimer<_ctrl>::start(gboolean (_ctrl::*)(_timerinfo*), _ctrl* const)'
[Warning] E:\dnc-imexchange\dnc-imexchange.cpp:52: note: candidates are: void purple_multitimer<T>::start(gboolean (T::*)(_timerinfo*), T*, guint) [with T = _ctrl]
I need to implement callbacks in such way.
If you want some good quality callbacks (able to call multiple functions at once, suitable for observer pattern), may I suggest boost::signals2.
If you just want to call one function as a callback you can use std::function:
void Foo(const std::function<bool (const int)> &callback)
{
const int number = 4;
if (callback(number))
{
std::cout << "Callback returned true!" << std::endl;
}
else
{
std::cout << "Callback returned false!" << std::endl;
}
}
// Use this if you have C++11
void CallFooLambda()
{
const auto lambda = [](const int number) -> bool
{
return number % 2;
};
Foo(lambda);
}
// Else use these functions
bool FooCallback(const int number)
{
return number % 2;
}
void CallFoo()
{
Foo(&FooCallback);
}
The _ctrl is a const pointer, and the function you try to call require a non-const ptr-to _ctrl (pthis).
Can you define pthis as follows?
T *pthis const
That should make your code match the 'candidate' in the error message.
this is a pointer that you can't change.
Boost.Function is a good toolkit for simplifying callback syntax and implementation.
The Boost.Function library contains a
family of class templates that are
function object wrappers. The notion
is similar to a generalized callback.
It shares features with function
pointers in that both define a call
interface (e.g., a function taking two
integer arguments and returning a
floating-point value) through which
some implementation can be called, and
the implementation that is invoked may
change throughout the course of the
program.
Generally, any place in which a
function pointer would be used to
defer a call or make a callback,
Boost.Function can be used instead to
allow the user greater flexibility in
the implementation of the target.
Targets can be any 'compatible'
function object (or function pointer),
meaning that the arguments to the
interface designated by Boost.Function
can be converted to the arguments of
the target function object.