从pthread_create将多个参数传递给线程函数

时间:2013-04-26 07:02:42

标签: c pthreads posix

这是我在C中进行线程化的第一次尝试。我正在创建一个循环有界的缓冲区。我知道如何创建线程,但我看到的所有示例都只有接受一个void参数的线程函数,但不幸的是我的工作者规范要求我使用三个,如下所示:

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

这是我的pthread_create语句

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

我的readParams结构/作业

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

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

有关如何在传递给bufferRead函数后分配每个struct参数的任何建议将不胜感激。

4 个答案:

答案 0 :(得分:8)

那是因为你只是需要一个参数。当我们有多个值时(通常就是这种情况),我们将其封装到结构中。 pthread_create将调用的函数类型是不可协商的。在这个区域中,对函数指针进行类型转换可能会给您带来严重的麻烦。

#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;
}

答案 1 :(得分:4)

启动功能必须参数。所以你的方向是正确的:

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

然后,您需要在堆上分配变量,而不是在堆栈上分配:

struct readThreadParams *readParams;

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

之后你可以给它createThread

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

线程函数只需要1个参数(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;
}

答案 2 :(得分:1)

你得到了正确的方式。

函数原型应该像

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

并且在线程函数中对所需类型的参数进行类型转换。这应该是

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

不能直接将多个参数传递给pthread函数。因此大多数形成为结构并传递给函数。

有关pthreads的详细信息,请参阅this教程。

答案 3 :(得分:0)

此示例与预处理程序滥用相关,但我喜欢它,因为它演示了模仿默认参数值。

#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef char *BoundedBuffer;

struct read_thread_param {  
    pthread_t thread;                                                 
    BoundedBuffer buffer;                                                        
    char* data;                                                             
    int count;                                                              
}; 

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

void *buffer_read_entrance(void *object) {
    struct read_thread_param *param = object;
    if (param->thread != 0) {
        buffer_read(&param->buffer, param->data, param->count);
        free(param);
        return NULL;
    }

    param = malloc(sizeof *param);

    /* TODO: Handle allocation error */
    assert(param != NULL);

    memcpy(param, object, sizeof *param);

    /* TODO: Handle thread creation error */
    assert(pthread_create(&param->thread, NULL, buffer_read_entrance, param) == 0);
    return NULL;
}

#define buffer_read_entrance(...) buffer_read_entrance(&(struct read_thread_param) { .thread = 0, __VA_ARGS__ })
void buffer_read(BoundedBuffer* buffer, char* data, int count);

int main(void) {
    buffer_read_entrance(.buffer = "hello world", .count = 42);
}