2012-07-18 19 views
5

私はOSXでいくつかのコードを構築しようとしているので、pthread_timedjoin_npに依存しないようにする方法を見つけようとしています。の代わりにpthread_timedjoin_np

今、私はpthread_timedjoin_npを実行しているスレッドのキューを持っていますが、戻ってこないとキューに戻ってきます。

スレッドごとに呼び出されるthread_functionの最後には、pthread_exit(0)があります。受信スレッドはゼロの戻り値をチェックできます。

私は同様の効果を得るためにpthread_cond_timedwait()を使用しようと思っていたかもしれないと思っていますが、私は一歩足りません。

私はワーカースレッドAシグナルを条件とし、mutex内でpthread_exit()を実行できると思っていました。ワーカースレッドBがシグナルを起こしてからpthread_join()を呼び出すことができました。問題は、スレッドBがどのスレッドが条件付き信号を投げたのかを知らないことです。条件信号の一部として明示的に渡す必要がありますか?ここで

おかげ

デレク

+0

ない重複したが、回答の一部が役に立つかもしれます。http:// stackoverflowの。com/questions/73468/non-blocking-pthread-join – Corbin

答えて

1

プロデューサ - コンシューマキュー。それらのスレッドが終了する前に、そのスレッドが(もしあれば)待ち行列にキューする*ようにします。待ち行列を待ちます。

ポーリングなし、待ち時間なし。

現在の設計では、返されたスレッドはvalueptrを取得して破棄されるようにjoin()する必要があります。

タスクアイテムが決して終了しないスレッドにキューイングされる本当のスレッドプールにいつか移動できます(スレッドの作成/終了/破棄のオーバーヘッドを排除します)。

+0

re:本物のスレッドプールです。私はQtフレームワークで作業しています。以前はプール/将来のモデルを使用しましたが、このコードの移植性の名前でそのコードを使用できるかどうかはわかりません。 – Derek

+0

これは元々メインスレッドがすべてのワーカーをキューに投げ込んでいただけですが、作業を終えたときに待ち行列に自分自身を追加し、スレッドは、そのキューからスレッドを取り出し、それに参加することを知っています。 – Derek

4

pthread_timedjoin_npのポータブルな実装です。それは少し高価なのですが、それは完全なドロップイン置換だ:私はその場でこれを書いて、それをテストしていないので、

struct args { 
    int joined; 
    pthread_t td; 
    pthread_mutex_t mtx; 
    pthread_cond_t cond; 
    void **res; 
}; 

static void *waiter(void *ap) 
{ 
    struct args *args = ap; 
    pthread_join(args->td, args->res); 
    pthread_mutex_lock(&args->mtx); 
    args->joined = 1; 
    pthread_mutex_unlock(&args->mtx); 
    pthread_cond_signal(&args->cond); 
    return 0; 
} 

int pthread_timedjoin_np(pthread_t td, void **res, struct timespec *ts) 
{ 
    pthread_t tmp; 
    int ret; 
    struct args args = { .td = td, .res = res }; 

    pthread_mutex_init(&args.mtx, 0); 
    pthread_cond_init(&args.cond, 0); 
    pthread_mutex_lock(&args.mtx); 

    ret = pthread_create(&tmp, 0, waiter, &args); 
    if (ret) goto done; 

    do ret = pthread_cond_timedwait(&args.cond, &args.mtx, ts); 
    while (!args.joined && ret != ETIMEDOUT); 

    pthread_mutex_unlock(&args.mtx); 

    pthread_cancel(tmp); 
    pthread_join(tmp, 0); 

    pthread_cond_destroy(&args.cond); 
    pthread_mutex_destroy(&args.mtx); 

    return args.joined ? 0 : ret; 
} 

はわずかな誤差があるかもしれませんが、コンセプトは音です。

+0

投稿する前に、私は実際にマーティンズに似た計画を考え出しました。それがうまくいけば、これを試してみましょう。 – Derek

+0

Martinのソリューションは、無駄なオーバーヘッドがなく、概念的に優れているという観点からはよりクリーンです。 Mineは、移植性のない関数を置き換えるだけで、何も再設計せずに移植性のないコードを修正することができます。 –

0

溶液alarm

pthreadはキャンセルを有効にする必要がありますので、外部で停止することができます(pthread_timedjoin_npを含む)。

pthread_timedjoin_np返信ETIMEOUT待ってから。

  1. セットalarmを使用すると、alarmも「タイムアウト」信号を与えることができます。
  2. ハンドラでは、ちょうどpthread_cancelです。 (これを実行するタイムアウトのみ)。
  3. pthread_joinメインスレッドです。
  4. 私はここでテストコードを書くalarm

をリセットします。github