2013-04-26 41 views
7

đây là nỗ lực đầu tiên của tôi trong luồng trong C. Tôi đang tạo bộ đệm được bao quanh theo chiều tròn. Tôi biết làm thế nào để tạo ra các chủ đề, nhưng tất cả những ví dụ tôi đã thấy chức năng chỉ có ren mà chấp nhận một tham số có hiệu lực, nhưng tiếc là đặc điểm kỹ thuật công nhân của tôi đòi hỏi tôi phải sử dụng ba, như thể hiện ở đây:Chuyển nhiều đối số đến hàm chuỗi từ pthread_create

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

Đây là pthread_create của tôi tuyên bố

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

Và readParams tôi struct/tập

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

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

Bất kỳ lời khuyên về cách gán mỗi thông số của struct sau khi đi qua cho b Hàm ufferRead sẽ được đánh giá cao.

Trả lời

8

Đó là vì bạn chỉ thực sự cần một thông số. Khi chúng ta có nhiều hơn một giá trị, như trường hợp điển hình, chúng ta gói gọn nó vào một cấu trúc. Loại chức năng mà pthread_create sẽ gọi là không thể thương lượng. Đây là khu vực mà việc nhập con trỏ hàm của bạn có thể khiến bạn gặp rắc rối nghiêm trọng.

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

-1 chuyển biến cục bộ sang một chuỗi khác –

+0

Nếu đó là biến cục bộ trong chính, đó không phải là vấn đề. Nếu bạn thoát khỏi chính thì chương trình của bạn sẽ chấm dứt để biến luôn luôn tồn tại trong khi chương trình của bạn đang chạy. – jcoder

+1

@jcoder Rời khỏi 'main' không có nghĩa là chấm dứt chương trình ngay lập tức. Và biến tự động (không phải đống, không tĩnh) cho giao tiếp giữa các luồng là một ý tưởng đáng ngờ nhất. –

1

Bạn đã đi đúng hướng.

Nguyên mẫu chức năng nên được như thế

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

Và định kiểu lập luận để loại yêu cầu trong chức năng thread. Ở đây, phải là

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

Không thể trực tiếp chuyển nhiều hơn một đối số đến chức năng pthread. do đó chủ yếu được hình thành như cấu trúc và được truyền cho hàm.

Tham khảo this hướng dẫn để biết thêm chi tiết về pthreads.

+0

Cảm ơn bạn đã trả lời nhanh! Chỉ cần tự hỏi, nhưng có cách nào để vẫn sử dụng nguyên mẫu chức năng tôi hiện đang có? – ChrisDevWard

+0

bạn có thể định kiểu và tạo. Nhưng không sử dụng. vì vậy 'void *() (void *)' được khuyến nghị. – Jeyaram

+0

@ChrisDevWard Không, bạn không thể.Vâng, cách duy nhất để sử dụng nguyên mẫu đó là gọi nó trực tiếp từ hàm void * start_routine (void *) của bạn mà thư viện pthread sẽ gọi, nhưng điều đó sẽ vô tình giới thiệu chi phí của một cuộc gọi hàm khác. –

4

Chức năng bắt đầu phải có đối số. Vì vậy, hướng của bạn là đúng:

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

Sau đó, bạn cần phải phân bổ biến trên đống, không phải trên stack:

struct readThreadParams *readParams; 

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

Sau đó bạn có thể cung cấp cho nó createThread:

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

Chức năng chủ đề chỉ nhận được 1 đối số (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; 
} 
0

Ví dụ này giới hạn về lạm dụng tiền xử lý, nhưng tôi thích nó vì nó thể hiện bắt chước các giá trị đối số mặc định.

#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); 
} 
Các vấn đề liên quan