7

这是我第一次尝试在 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 函数后分配每个结构参数的建议将不胜感激。

4

4 回答 4

11

那是因为你真的只需要一个参数。当我们有多个值时,通常情况下,我们将其封装到一个结构中。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;
}
于 2013-04-26T07:26:55.523 回答
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;
}
于 2013-04-26T07:11:14.787 回答
2

你走对了。

函数原型应该像

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

并将参数类型转换为线程函数中所需的类型。这里应该是

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

不能直接将多个参数传递给 pthread 函数。所以主要形成为结构并传递给函数。

有关 pthread 的更多详细信息,请参阅教程。

于 2013-04-26T07:09:09.873 回答
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);
}
于 2013-04-26T10:58:30.250 回答