IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

pthread でキューを書いてみる

この記事は全然ダメだったようです。

こちらに新しく書き直しました。
http://d.hatena.ne.jp/amachang/20080617/1213694238

こんな感じになった

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <pthread.h>

static int*             q;
static int              n; // 次に入れるインデックス
static int              l; // 次に出すインデックス
static int              s;
static pthread_mutex_t  m;
static pthread_cond_t   c;

void initQ (size_t size) {
    n = 0;
    l = 0;
    s = size;

    // キューの領域確保
    q = (int*)malloc(s * sizeof(int));
    // -1 は空の意味
    memset(q, -1, s * sizeof(int));

    // ミューテックスと cond の初期化
    pthread_mutex_init(&m, NULL);
    pthread_cond_init(&c, NULL);
}

void destroyQ () {
    // キューの解放
    free(q);

    // ミューテックスと cond の解放
    pthread_mutex_destroy(&m);
    pthread_cond_destroy(&c);
}

void enQ (int data) {
    // ロック
    pthread_mutex_lock(&m);

    // キューが空いてれば
    if (q[n % s] == -1) {

        // キューにデータを入れる
        q[n++ % s] = data;
        printf("thread[%p]: enQ(%d)\n", pthread_self(), data);

        // ロック解除
        pthread_mutex_unlock(&m);

        // データが入ったよ!と待ちスレッドに通知
        pthread_cond_signal(&c);

        // 実行権をゆずるくん
        sleep(0); // pthread_yield();
    }

    // キューがいっぱい
    else {
        // ロック解除
        pthread_mutex_unlock(&m);

        // 実行権をゆずるくん
        sleep(0); // pthread_yield();

        // もっかい挑戦
        enQ(data);
    }
}

int deQ () {
    // ロック
    pthread_mutex_lock(&m);

    // データが入るまで待ちまくる
    while (q[l % s] == -1) pthread_cond_wait(&c, &m);

    // データを取る
    int r = q[l %s];
    q[l++ % s] = -1;
    printf("thread[%p]: deQ(%d)\n", pthread_self(), r);

    // ロック解除
    pthread_mutex_unlock(&m);

    return r;
}

実行してみる

main を作って

void* thread_enQ(void* p) {
    while(1) {
        enQ((int)p);
    }
}

void* thread_deQ(void* p) {
    while(1) {
        deQ();
    }
}

int main (int argc, char** argv) {
    initQ(10);

    pthread_t t0;
    pthread_t t1;

    pthread_create(&t0, NULL, thread_enQ, (void*)0);
    pthread_create(&t1, NULL, thread_enQ, (void*)1);

    pthread_t t2;
    pthread_t t3;

    pthread_create(&t2, NULL, thread_deQ, NULL);
    pthread_create(&t3, NULL, thread_deQ, NULL);


    pthread_join(t0, NULL);

    destroyQ();
    return 0;
}

実行!

$ gcc queue.c && ./a.out
thread[0xb0081000]: enQ(0)
thread[0xb0185000]: deQ(0)
thread[0xb0103000]: enQ(1)
thread[0xb0185000]: deQ(1)
thread[0xb0081000]: enQ(0)
thread[0xb0185000]: deQ(0)
thread[0xb0103000]: enQ(1)
thread[0xb0185000]: deQ(1)
thread[0xb0081000]: enQ(0)
thread[0xb0185000]: deQ(0)
:
:

おおお。できたできた

Mac では

pthread_yield がないと言われた><
なので sleep(0) でやったけどいいのかな