Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing multiple arguments to threaded function from pthread_create

Tags:

c

posix

pthreads

this is my first attempt at threading in C. I am creating a circularly bounded buffer. I know how to create the thread, but all examples I have seen only have threaded functions that accept one void parameter, but unfortunately my worker's specification requires me to use three, as shown here:

void bufferRead(BoundedBuffer* buffer, char* data, int count) {
    pthread_mutex_lock(&buffer->mutexBuffer);
    <snip>
    pthread_mutex_unlock(&buffer->mutexBuffer);
}

Here is my pthread_create statement

pthread_create(&buffer.readThread, NULL, (void *)bufferRead, &readParams)

And my readParams struct/assignments

struct readThreadParams {                                                   
    BoundedBuffer b;                                                        
    char* data;                                                             
    int count;                                                              
};                                                                          

struct readThreadParams readParams;                                         
readParams.b = buffer2;                                                     
readParams.data = out_array;                                                
readParams.count = in_size;

Any advice on how to assign each of the struct's parameters after passing to the bufferRead function would be greatly appreciated.

like image 907
ChrisDevWard Avatar asked Apr 26 '13 07:04

ChrisDevWard


People also ask

How do I pass multiple arguments to a thread function?

For cases where multiple arguments must be passed, this limitation is easily overcome by creating a structure which contains all of the arguments, and then passing a pointer to that structure in the pthread_create() routine. All arguments must be passed by reference and cast to (void *).

Which argument of pthread_create is thread entry code?

pthread_t is the data type used to uniquely identify a thread. It is returned by pthread_create() and used by the application in function calls that require a thread identifier. The thread is created running start_routine, with arg as the only argument.

What is the last argument passed to the pthread_create () function?

The last parameter of pthread_create() is passed as the argument to the function, whereas the return value is passed using pthread_exit() and pthread_join() .

What is the use of pthread_join () and pthread_exit () function?

On return from a successful pthread_join() call with a non-NULL value_ptr argument, the value passed to pthread_exit() by the terminating thread shall be made available in the location referenced by value_ptr. When a pthread_join() returns successfully, the target thread has been terminated.


3 Answers

That's because you only really need one parameter. When we have more than one value, as is typically the case, we encapsulate that into a struct. The function type that pthread_create will call is non-negotiable. This is an area where type-casting your function pointer can get you into serious trouble.

#include <pthread.h>
#include <stdlib.h>

struct BoundedBuffer {
    pthread_t readThread;
    pthread_mutex_t mutexBuffer;
} buffer2;

struct readThreadParams {
    struct BoundedBuffer b;
    char* data;
    int count;
};

void *bufferRead (void *context) {
    struct readThreadParams *readParams = context;

    pthread_mutex_lock(&readParams->b.mutexBuffer);
    //<snip>
    pthread_mutex_unlock(&readParams->b.mutexBuffer);

    return NULL;
}

int main(void) {
    int ret;
    char *out_array = malloc(42);
    size_t in_size = 42;

    struct readThreadParams readParams;
    readParams.b = buffer2;
    readParams.data = out_array;
    readParams.count = in_size;

    /* I presume that by "buffer", you really meant the .b member of
     * struct readThreadParams.  Further, this must have a member
     * named readThread of type pthread_t, etc.
     */
    ret = pthread_create(&readParams.b.readThread, NULL, bufferRead, &readParams);

    if (!ret) {
        pthread_join(&readParams.b.readThread, NULL);
    }

    free(out_array);

    return ret;
}
like image 85
Daniel Santos Avatar answered Nov 10 '22 03:11

Daniel Santos


Start function has to take argument. So your direction is right:

struct readThreadParams {                                                   
    BoundedBuffer *b; 
    char *data;                                                             
    int count;                                                              
};     

Then, you need to allocate the variable on heap, not on stack:

struct readThreadParams *readParams;

readParams = malloc(sizeof(*readParams));
readParams->b = buffer2;                                                     
readParams->data = out_array;                                                
readParams->count = in_size;

After which you can give it createThread:

pthread_create(&buffer.readThread, NULL, bufferRead, readParams);

Thread function shall take only 1 argument (void*):

void *bufferRead(void *arg)
{
    struct readThreadParams *params = arg;
    BoundedBuffer *buffer = params->b;
    char* data = params->data;
    int count = params->count;

    pthread_mutex_lock(&buffer->mutexBuffer);
    <snip>
    pthread_mutex_unlock(&buffer->mutexBuffer);

    return NULL;
}
like image 38
Valeri Atamaniouk Avatar answered Nov 10 '22 03:11

Valeri Atamaniouk


You got in the right way.

The function prototype should be like

void*  bufferRead(void *arg)
{
   ....
}

And typecast the argument to required type in thread function. Here, it should be

void*  bufferRead(void *arg)
{
     struct readThreadParams *input = (struct readThreadParams*)arg;
}

Passing more than one arguments to pthread function is not possible directly. so mostly formed as structure and passed to the function.

Refer this tutorial for more details on pthreads.

like image 33
Jeyaram Avatar answered Nov 10 '22 03:11

Jeyaram