9

奇妙な問題があります。私は次のコードを持っています:

    dbg("condwait: timeout = %d, %d\n", 
        abs_timeout->tv_sec, abs_timeout->tv_nsec);
    ret = pthread_cond_timedwait( &q->q_cond, &q->q_mtx, abs_timeout );
    if (ret == ETIMEDOUT)
    {
      dbg("cond timed out\n");
      return -ETIMEDOUT;
    }

dbggettimeofdayすべての行の前に呼び出し、行の前に時間を追加します。その結果、次の出力が得られます。

    7.991151: condwait: timeout = 5, 705032704
    7.991158: cond timed out

ご覧のとおり、2つのデバッグ行の間を通過したのはわずか7マイクロ秒ですが、pthread_cond_timedwait返されETIMEDOUTます。これはどのように起こりますか?cond変数を初期化するときに、時計を別のものに設定しようとしました。

int ret;
ret = pthread_condattr_init(&attributes);
if (ret != 0) printf("CONDATTR INIT FAILED: %d\n", ret);
ret = pthread_condattr_setclock(&attributes, CLOCK_REALTIME);
if (ret != 0) printf("SETCLOCK FAILED: %d\n", ret);
ret = pthread_cond_init( &q->q_cond, &attributes );
if (ret != 0) printf("COND INIT FAILED: %d\n", ret);

(エラーメッセージは印刷されません)。CLOCK_REALTIMEとの両方を試しましCLOCK_MONOTONICた。

このコードはブロッキングキューの一部です。5秒以内にこのキューに何も入れられない場合、何か他のことが起こるような機能が必要です。を使用しない場合、ブロッキングキューは正常に機能するため、ミューテックスと条件は両方とも初期化されますpthread_cond_timedwait

4

4 に答える 4

16

pthread_cond_timedwaitは、相対時間ではなく絶対時間を要します。タイムアウト値に現在の時間を追加して、待機時間を絶対にする必要があります。

于 2009-03-19T03:05:56.070 に答える
8

timespec通常、異常なタイムアウトの原因はオーバーフローです。EINVAL
を確認します。

void timespec_add(struct timespec* a, struct timespec* b, struct timespec* out)
{
    time_t sec = a->tv_sec + b->tv_sec;
    long nsec = a->tv_nsec + b->tv_nsec;

    sec += nsec / 1000000000L;
    nsec = nsec % 1000000000L;

    out->tv_sec = sec;
    out->tv_nsec = nsec;
}
于 2012-11-09T07:07:58.623 に答える
4

条件変数は誤ってブロックを解除する可能性があります。ループでチェックし、毎回条件をチェックする必要があります。おそらくタイムアウト値も更新する必要があります。

pthread_cond_timedwait hereのドキュメントが見つかりました。

条件変数を使用する場合、スレッドが続行する必要がある場合に真になる各条件待機に関連付けられた共有変数を含むブール述語が常に存在します。pthread_cond_timedwait() または pthread_cond_wait() 関数からの偽のウェイクアップが発生する可能性があります。pthread_cond_timedwait() または pthread_cond_wait() からの戻りは、この述部の値について何も意味しないため、そのような戻り時に述部を再評価する必要があります。

于 2009-03-19T03:07:00.090 に答える