C++11のスレッドセーフなキュー
質問
私が取り組んでいるプロジェクトは、ファイルのコレクション上で作業を行うために複数のスレッドを使用します。各スレッドは処理されるファイルのリストにファイルを追加することができるので、私はスレッドセーフなキューを(私が考えたものを)一緒に置いた。関連する部分を以下に示します。
// qMutex is a std::mutex intended to guard the queue
// populatedNotifier is a std::condition_variable intended to
// notify waiting threads of a new item in the queue
void FileQueue::enqueue(std::string&& filename)
{
std::lock_guard<std::mutex> lock(qMutex);
q.push(std::move(filename));
// Notify anyone waiting for additional files that more have arrived
populatedNotifier.notify_one();
}
std::string FileQueue::dequeue(const std::chrono::milliseconds& timeout)
{
std::unique_lock<std::mutex> lock(qMutex);
if (q.empty()) {
if (populatedNotifier.wait_for(lock, timeout) == std::cv_status::no_timeout) {
std::string ret = q.front();
q.pop();
return ret;
}
else {
return std::string();
}
}
else {
std::string ret = q.front();
q.pop();
return ret;
}
}
しかし、たまに
if (...wait_for(lock, timeout) == std::cv_status::no_timeout) { }
ブロックの中でセグメンテーションフォールトが発生することがあります。これはどうしてなのでしょうか?私の理解では
wait_for
が返すのは
cv_status::no_timeout
を返すだけであり、これは
FileQueue::enqueue
が新しいアイテムをキューにプッシュした後でなければ発生しません。
どのように解決するのですか?
規格によると
condition_variables
は、たとえイベントが発生していなくても、 疑似的にウェイクアップすることが許されています。偽のウェイクアップが発生した場合、それは
cv_status::no_timeout
を返します (タイムアウトではなくウェイクアップしたため)。これに対する正しい解決策は、もちろん、ウェイクアップが実際に正当であったかどうかを手続きする前にチェックすることです。
詳細は標準の§30.5.1 [thread.condition.condvar]で指定されています。
-notify_one()の呼び出し、notify_all()の呼び出し、abs_timeで指定された絶対時間切れ(30.2.4)、またはスプリアスで合図されるとブロックを解除します。
...
を返します。 abs_time で指定された絶対タイムアウト(30.2.4)が経過した場合は cv_status::timeout ,それ以外は cv_status::no_timeout を返します.
関連
-
[解決済み】クラステンプレートの引数リストがない
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み】浮動小数点例外エラーが発生する: 8
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み】Android "ビュー階層を作成した元のスレッドだけが、そのビューに触れることができる"
-
[解決済み] 他のスレッドからGUIを更新するにはどうすればよいですか?
-
[解決済み] Javaにおける "implements Runnable "と "extends Thread "の違いについて
-
[解決済み] プロセスとスレッドの違いは何ですか?
-
[解決済み] JavaScriptでStackとQueueを実装するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++でint型に無限大を設定する
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み] 数値定数の前にunqualified-idを付けて、数値を定義することを期待する。