4

高速なプロデューサーがキューにデータを挿入し、低速なコンシューマーがデータを消費するユース ケースがあります。私が直面している問題は、時間の経過とともにキューのサイズが継続的に増加することです。std::queue が同時読み取りと書き込みのミューテックスと条件変数によって保護されるクラス実装があります。

プロデューサーが MAX_THRESHOLD に達した後、キューへのデータの挿入を停止し、コンシューマーがある程度の量のデータを消費すると、プロデューサーにデータをキューに挿入するように信号を送る場合に、これをどのように適応させることができますか。

誰かがサンプル実装を提供できますか?

また、クラスの実装を変更せずに、プロデューサーとコンシューマーに別の同期レイヤーを追加することで、この問題を解決できますか?

4

2 に答える 2

4

また:

a) キューのサイズが MAX_THRESHOLD に達した場合にプロデューサをブロックするバインドされたキュー クラスを使用します。これは、キュー クラスを変更することを意味しますが、これは望ましくない場合があります。

b) 「プール キュー」を使用します。これは、起動時に MAX_THRESHOLD オブジェクトでいっぱいにする別の無制限のブロッキング キューです。プロデューサはプールからオブジェクトを取得してロードし、プロデューサのキューに入れます。プロデューサはコンシューマからオブジェクトを取得し、それらを「消費」してプールに返します。これは、ポインターまたはおそらく参照を使用することを義務付けていますが、これは望ましくない場合があります。

c) MAX_THRESHOLD カウントで初期化されたセマフォを使用して、(b) と同様の方法でメッセージ トークンを表します。プロデューサーはキューに入る前にユニットを取得する必要があり、コンシューマーはメッセージ オブジェクトの処理が完了したときにユニットをポストします。

私は(b)をよく使います。

于 2013-03-10T21:40:39.613 に答える
3

pthreadを使用した「バウンドキュー」のコードスニペット:

#include <queue>
#include <pthread.h>

template <class T, size_t UpperLimit>
class BoundedQueue {
  std::queue<T> q_;
  pthread_mutex_t mtx_;
  pthread_cond_t cv_not_empry_;
  pthread_cond_t cv_not_full_;

  // lock/unlock helper
  struct auto_locker {
    auto_locker(pthread_mutex_t* pm) : pm_(pm)
      { pthread_mutex_lock(pm_); }
    ~auto_locker()
      { pthread_mutex_unlock(pm_);}
    pthread_mutex_t *pm_;
  };

public:
  BoundedQueue() { /* initialize member... */ }
  ~BoundedQueue() { /* uninitialize member...*/ }
  // for Producer
  void push(T x) {
    auto_locker lk(&mtx_);
    while (UpperLimit <= q_.size()) {
      pthread_cond_wait(&cv_not_full_, &mtx_);
    }
    q_.push(x);
    pthread_cond_broadcast(&cv_not_empry_);
    return ret;
  }
  // for Consumer
  T pop() {
    auto_locker lk(&mtx_);
    while (q_.empty()) {
      pthread_cond_wait(&cv_not_empry_, &mtx_);
    }
    T ret = q_.front();
    q_.pop();
    pthread_cond_broadcast(&cv_not_full_);
    return ret;
  }
}
于 2013-03-11T10:30:31.220 に答える