user5109370
user5109370

Reputation:

linux pthread - is there a way not to create all the members as static?

I'm using pthread to create threads (in c++ application):

int result = pthread_create( &thread, NULL, CMyClass::RunThread, 0);

and CMyClass::RunThread must be static function (in order to be compile):

static void *RunThread(void *ptr);

so all the class members and helper functions which are being called from RunThread, must be static too.

It seem that I have to many (~5) static members. (seem not a good programming to me...)

Is there a better way ? more elegant way ?

thanks

Upvotes: 3

Views: 164

Answers (2)

Jens Munk
Jens Munk

Reputation: 4725

I do this quite often and therefore, I have created a small pattern for executing member functions

#include <pthread.h>
#include <iostream>

template<class T, void*(T::*thread_func)(void*)>
class pthread_launcher {
public:
  pthread_launcher(T* obj=NULL, void* arg=NULL) : _obj(obj), _arg(arg) {}
  void *launch() { return (_obj->*thread_func)(_arg);}
private:
  /// Object pointer
  T* _obj;
  /// Command argument for member function
  void *_arg;
};

// Launch thread function
template<class T>
void *launch_member_function(void *obj)
{
  T* launcher = reinterpret_cast<T*>(obj);
  return launcher->launch();
}

typedef struct thread_arg {
  float fData;
} thread_arg_t;

class A {
 public:
  void* nonStaticFunction(void* arg) {
    std::cout << "Executing" << std::endl;
    return NULL;
  }
};

// (1)
template class pthread_launcher<A,&A::nonStaticFunction>;


int main() {

  thread_arg_t arg;
  arg.fData = 1.0f;

  // Laucher (2)
  pthread_launcher<A, &A::nonStaticFunction> launcher;

  // Initialize using function pointer and optional argument (2)
  launcher = pthread_launcher<A,&A::nonStaticFunction>(&a, &arg);

  A a;

  pthread_t thread;  
  // Start thread (4)
  pthread_create(&thread, NULL,
         launch_member_function<pthread_launcher<A,&A::nonStaticFunction> >,
         &launcher);

  pthread_join(thread,NULL);
  return 0;
}

The only thing you need to do over and over again, is what happens at (1), (2), (3) and (4).

Upvotes: 0

Non-maskable Interrupt
Non-maskable Interrupt

Reputation: 3911

  1. Pass this pointer to pthread_create
  2. start a stub function which resolve this
  3. call your real function

The pseudo code looks like this:

// static stub function
void* MyClass::thread_stub(void* p) {
  MyClass* c = static_cast<MyClass*>(p);
  return c->thread_func();
}

void* MyClass::thread_func() {
    return NULL;
}

int MyClass::start() {
    pthread_create(....thread_stub, this);
}

Upvotes: 1

Related Questions