Reputation: 965
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.
Upvotes: 8
Views: 64065
Reputation: 3295
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;
}
Upvotes: 15
Reputation: 15632
This example borders on preprocessor abuse, but I like it because it demonstrates mimicking default argument values.
#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);
}
Upvotes: 0
Reputation: 5163
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;
}
Upvotes: 4
Reputation: 9474
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.
Upvotes: 3