这是我在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参数的任何建议将不胜感激。
答案 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(¶m->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(¶m->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);
}