2016-11-23 5 views
3

コンシューマのみがブロックされる単一のプロデューサと単一のコンシューマでバッファを実装したいと考えています。ここで重要な点は、キューがいっぱいになるとプロデューサが更新を削除できることです。コンシューマのみをブロックする単一のプロデューサ/コンシューマ循環バッファ

私は待ち時間のない実装の変換を検討しましたが、一見して、消費者に通知を失うことなく新しいデータが到着したことを通知する簡単な方法はないようです。

Object ar[SIZE]; 
int head = 0, tail = 0; 
sem_t semItems; // initialized to 0 

void enqueue(Object o) { 
    int val; 
    sem_getvalue(&semItems, &val); 
    if (val < SIZE - 1) { 
     ar[head] = o; 
     head = (head + 1) % SIZE; 
     sem_post(&semItems); 
    } 
    else { 
     // dropped 
    } 
} 
Object dequeue(void) { 
    sem_wait(&semItems); 
    Object o = ar[tail]; 
    tail = (tail + 1) % SIZE; 
    return o; 
} 

は、このコードのいずれかの安全性の問題があります。だから私は(いくつかのエラー処理の詳細については、明確にするために省略)カウンティングセマフォを使用して、以下の非常に単純なアプローチに定住しましたか?私は普及した文献のどこにでもそのような実装を見ないことに驚いた。もう1つの疑問は、 sem_post()がブロックするかどうかです(linuxでは futex_wake()を呼び出します)。簡単なソリューションももちろん歓迎します。

編集:リーダーとライターの間にスペースを残して編集したコードです(Mayurkの回答を参照)。

+0

なぜ消費者のみをブロックする必要があるのですか? –

+0

@SumitGemini多くのトラフィックがある場合、プロデューサはハードウェアと話すので、消費者はプロデューサよりも遅く実行する必要があります。これは私が見ているアプローチの1つに過ぎません。暗黙のCASループが実際にそれを悪化させる可能性があります。 – wds

+0

@SumitGeminiはネイティブのC++セマフォの提案に直面しました。http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2043.html#SemaphoreTypes – wds

答えて

2

この実装では1つの問題があります。次のシーケンスを考えてみましょう。

  1. バッファーはいっぱいですが、コンシューマーはまだ開始されていないものとします。したがって(head = 0、tail = 0、sem_val = SIZE)。
  2. dequeue()はコンシューマスレッドから呼び出されます。 sem_wait()は成功します。だからそのインスタンス(head = 0、tail = 0、sem_val = SIZE-1)。消費者はar [0]の読み込みを開始します。
  3. スレッドスイッチがあります。 enqueue()はプロデューサスレッドから呼び出されます。 sem_getvalue()はSIZE-1を返します。だから、プロデューサーはar [0]に書きます。

基本的には、読み書き操作のためのmutex保護が必要だと思います。しかし、mutexを追加するとスレッドがブロックされる可能性があります。だから私はあなたがこのロジックから期待される行動を取るかどうかはわかりません。

+0

あなたは正しいですこれは、バッファ内の1つの場所を犠牲にすることで簡単には解決できません。つまり、val wds

+0

@wdsいいえ、この問題はいつでも直面する可能性があります。例(head = 3、tail = 3、sem_val = SOMTHING)。この場合でさえ、上記の動作シーケンスがバッファの破損につながる場合。 – MayurK

+0

デキューは、エンキューがセマフォにポストすることによって "エンキュー"された後、バッファ内の位置からのみ読み取ることができます。私はあなたが暗示している状況がどのように存在するかを見ません。 – wds