How to make a pthreads pool run arbitrary routines

Viewed 267

I am implementing a threads pool using pthreads. All threads share a work queue and the host main thread pushes the work into this shared queue. My implementation will be used as a library, it should be able to run any applications, therefore I want the work here be an arbitrary routine with arbitrary number of arguments. I searched this on the Internet but didn't find any solution.

Part of most implementations is like this:

typedef struct
{
  void* (*routine)(void*); // work routine
  void* arg; //work routine argument
} _work;

typedef struct
{
  _work *work;
  pthrea_mutex_t work_lock;
  pthread_cond_t work_ready;
} _tpool;

static _tpool *tpool = NULL;

void* thread_routine(void* args)
{
  _work *work;
  while(1){
    pthread_mutex_lock(&tpool->work_lock);
    while(!tpool->work){
        pthread_cond_wait(&tpool->work_ready, &tpool->work_lock);
    }
    work = tpool->work;
    pthread_mutex_unlock(&tpool->work_lock);
    work->routine(work->arg);
  }
  return NULL;
}

When threads are created, they are waiting until a work is pushed into the work queue. In this example, I assume there is only one work in the queue. The problem here is that the work routine has only one argument, although this argument could contain multiple arguments if it is a struct in C. If an application is given, we can easily define such a struct, but since it is a library, it should handle arbitrary applications. The question is how to handle an arbitrary routine which has unknown number of arguments?

For instance, I would like the implementation be like this:

typedef struct
{
  void* (*routine)(void*); // work routine
  void** args; // point to a list of arguments
  int num_args; // number of arguments
} _work;

and in the thread_routine(), it should launch

work->routine(work->args[0], work->arg[1], work->arg[2], ...);

The point here is that we do not know what routine the thread will execute. It could be any routine. For example, the routine here could be:

work_1(int a);

work_2(int a, double b)

work_3(float* a, int c, double* b);

Any suggestions on how to achieve this goal? Thanks.

2 Answers
Related