web-dev-qa-db-ja.com

無効なpthread_t idがありますか?

特定のスレッドIDに対してpthread_joinを呼び出したいのですが、そのスレッドが開始されている場合のみです。安全な解決策は、変数を追加して、どのスレッドが開始されたかを追跡することです。ただし、次のコードのようなpthread_t変数のチェックが可能かどうかは疑問です。

pthread_t thr1 = some_invalid_value; //0 ?
pthread_t thr2 = some_invalid_value;

/* thread 1 and 2 are strated or not depending on various condition */
....

/* cleanup */
if(thr1 != some_invalid_value)
    pthread_join(&thr1);

if(thr2 != some_invalid_value)
    pthread_join(&thr2);

Some_invalid_valueが0または実装依存の「PTHREAD_INVALID_ID」マクロの場合

PS:私の仮定は、pthread_t型が比較可能で割り当て可能であること、に基づく仮定

PPS:無効なスレッドIDでpthread_joinを呼び出すのは未定義の動作だと思ったため、これを実行したかったのです。そうではない。ただし、以前に結合されたスレッドに参加するIS undefined behaviour。では、上記の「関数」が繰り返し呼び出されると仮定します。

50
shodanex

最初はあなたの仮定は間違っています。 pthread_tオブジェクトは不透明です。 Cでpthread_t型を直接比較することはできません。代わりにpthread_equalを使用する必要があります。

もう1つの考慮事項は、pthread_createが失敗すると、pthread_tの内容が未定義になることです。無効な値に設定されることはもうありません。

私の好みは、pthread_create呼び出しの戻り値を(スレッドIDとともに)保持し、それを使用して各スレッドが正しく開始されたかどうかを判別することです。

17
qbert220

Tonyが提案したように、この状況ではpthread_self()を使用できます。

しかし、しない比較thread_ts使用==または!=。使用する - pthread_equal

から - pthread_self manページ:

したがって、pthread_t型の変数は、Cの等価演算子(==)を使用して移植可能に比較できません。代わりにpthread_equal(3)を使用してください。

11
Mat

私は最近、この同じ問題に遭遇しました。 pthread_create()が失敗した場合、未定義の無効な値がphtread_t構造体に格納されてしまいました。その結果、pthread_create()が成功した場合にtrueに設定される各スレッドに関連付けられたブール値を保持します。

その後、私がする必要があるのは次のとおりです。

void* status;
if (my_thread_running) {
  pthread_join(thread, &status);
  my_thread_running = false;
}
1
It'sPete

残念ながら、_pthread_t_がポインターであるシステムでは、2つの引数が異なるスレッドを参照している場合でも、pthread_equal()は等値を返します。スレッドは終了でき、同じ_pthread_t_ポインター値を使用して新しいスレッドを作成できます。

1

私はpthreadを使用するコードをC++アプリケーションに移植していましたが、同じ質問がありました。参加するかどうかを決定する.joinable()メソッドを持つC++ std::threadオブジェクトに切り替える方が簡単だと判断しました。

 if (t.joinable()) t.join();

pthead_joinが失敗した結果として)不正なpthread_t値でpthread_createを呼び出すと、エラー戻り値だけでなく、セグフォールトが発生することがわかりました。

0
Mark Lakata

これは素晴らしい質問であり、C++クラスとコードテストでさらに議論したいと思っています。

一部のシステムのオプションの1つは、やり過ぎのように思えるかもしれませんが、私にとっては便利な方法ですが、ティアダウンシグナルを効率的に待ってから終了する以外の何もしないスレッドを開始することです。このスレッドは、アプリケーションの存続期間中は実行され続け、シャットダウンシーケンスの非常に遅い段階で停止します。その時点まで、このスレッドのIDは、ほとんどの目的で、「無効なスレッド」値として、またはより可能性の高い「初期化されていない」センチネルとして効果的に使用できます。たとえば、私のデバッグライブラリは通常、ミューテックスがロックされたスレッドを追跡します。これには、その追跡値を適切なものに初期化する必要があります。プラットフォームがINVALID_THREAD_IDを定義することをPOSIXがかなり愚かに拒否し、私のライブラリでmain()がロックできるようにしているため(pthread_selfチェックをpthread_createがロックトラッキングに使用できないようにする)、これが私が使用するようになったソリューションです。どのプラットフォームでも動作します。

ただし、静的スレッド参照を無効な値に初期化できるようにするには、もう少し設計作業が必要です。

0
breakpoint