web-dev-qa-db-ja.com

pthread_createからスレッド関数に複数の引数を渡す

これは、Cでのスレッド化の最初の試みです。循環境界バッファーを作成しています。スレッドの作成方法は知っていますが、これまでに見たすべての例には、1つのvoidパラメーターを受け入れるスレッド関数しかありませんが、残念ながら、ワーカーの仕様では、次に示すように3つを使用する必要があります。

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関数に渡した後、構造体の各パラメーターを割り当てる方法に関するアドバイスをいただければ幸いです。

7
ChrisDevWard

これは、実際にはneed 1つのパラメーターしかないためです。通常の場合のように、複数の値がある場合は、それを構造体にカプセル化します。 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;
}
8
Daniel Santos

開始関数は引数を取る必要があります。だからあなたの方向は正しいです:

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

あなたは正しい方法で得ました。

関数プロトタイプは次のようになります

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

そして、スレッド関数で必要な型に引数を型キャストします。ここでは、

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

Pthread関数に複数の引数を渡すことは直接できません。そのほとんどは構造体として形成され、関数に渡されます。

Pthreadの詳細については、 this チュートリアルを参照してください。

2
Jeyaram

この例はプリプロセッサの悪用に隣接していますが、デフォルトの引数値を模倣しているので気に入っています。

#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);
}
0
autistic