2017-06-07 9 views
0

共有優先度キュークラスを作成しました。
データの配信を停止するように通知するには、doneという記号を設定し、アプリケーションがキューからデータを読み書きすることを許可しないメソッドCancel()を使用します。 std::mutexstd::condition_variableと組み合わせてstd::atomic<bool>を使用することについてはわかりません。私の解決策が安全か、レース状態が発生する可能性がスレッドであるかどうかは、わからない:std :: atomicを使用した正確性<bool>とstd :: mutexの組み合わせ

Enqueue方法のオリジナルバージョンは次のとおりです。

std::deque<T> deque; 
std::mutex mtx; 
std::condition_variable cv; 
std::atomic<bool> done; 

SharedPriorityQueue() : done(false) 
{ 
} 

~SharedPriorityQueue() 
{ 
    Cancel(); 
} 

void Enqueue(T item) 
{ 
    if (done) 
    { 
     return; 
    } 

    std::lock_guard<std::mutex> lock(mtx); 
    deque.push_back(item); 
    cv.notify_one(); 
} 

しかし、変数done(アトミックブール値)することができから分離mutexによるロック機構?

void Cancel() 
{ 
    if (done) 
    { 
     return; 
    } 
    done = true; 

    cv.notify_all(); 
} 

怒鳴るデザインの最良の解決策は何ですか?私はこの構造を使用するキューをキャンセルする

// A) 
void Enqueue(T item) 
{ 
    if (done) 
    { 
     return; 
    } 

    { 
     std::lock_guard<std::mutex> lock(mtx); // lock is released before notify call 
     deque.push_back(item); 
    } 
    cv.notify_one(); 
} 

// B) 
void Enqueue(T item) 
{ 
    { 
     std::lock_guard<std::mutex> lock(mtx); // done is atomic bool and protected by the lock along with data (deque) 
     if (done) // atomic bool 
     { 
      return; 
     } 

     deque.push_back(item); 
    } 
    cv.notify_one(); 
} 

// C) 
void Enqueue(T item) 
{ 
    { 
     std::lock_guard<std::mutex> lock(mtx); // done is NOT atomic bool and is protected by the lock along with data (deque) 
     if (done) // simple bool 
     { 
      return; 
     } 

     deque.push_back(item); 
    } 
    cv.notify_one(); 
} 

ウェイターは:

bool Dequeue(T& item) 
{ 
    std::unique_lock<std::mutex> lock(mtx); 
    while (!done && deque.empty()) 
    { 
     cv.wait(lock); 
    } 

    if (!deque.empty()) 
    { 
     item = deque.front(); 
     deque.pop_front(); 
    } 

    if (done) 
    { 
     return false; 
    } 
    return true; 
} 
+0

質問を絞り込んでください。フォーカスの不足があるようです。 –

+0

どのような焦点を意味しますか?質問から明らかでないことは何ですか?私は質問を指定します... – Dom

+0

すでに曖昧なスレッドライブラリでアトミックを使用することの「正確さ」をタイトルで尋ねています。次に、身体の中で2つの質問をしました。条件変数の前にロックが必要かどうか。多くの実装のどれが「より良い」ものであり、これもあいまいである。どちらかを選択し、可能な限り객관的に答えてください。 –

答えて

0

ノーマル/最も多いケースは、完了状態の可能性が高いだけで、終了時に使用されているのに対し、キューは、(行わない)準備ができていることでしょうです。アトミックを使用することで、完了したケースを最適化するのはほとんど意味がないかもしれません。

最適化対象を理解し、プロファイラを使用する必要があります。

1

正確性を保証するには、が取得するロックを保持する「条件」に関するデータを.wait(...)に変更する必要があります。

私は見つけることができるの明確な文がある規範的ではないものの:

共有変数が原子であっても、正しく待っ への変更を公開するために ミューテックスの下に修正されなければなりません糸。ここで

は:http://en.cppreference.com/w/cpp/thread/condition_variable

それは非常に明確に、正確にあなたの質問に答えます!

Cancel()は、mtxを保持する必要があります。それを原子にすると、助けが止まる。

私はMSVC++ Communityのどこにあるのか分かりませんが、私はそれがMSVC++ Communityの場合であることを知っています。

notify_one()(またはnotify_all())のときにロックを保持する必要はありませんが、「共有状態」(この場合はキューまたはフラグ)を変更するときに保持する必要があります。

+0

ありがとう、それは私が探していたことを説明している正確な答えです:-) – Dom

関連する問題