2012-03-06 7 views
0

クライアント(GUIとソケットを使用する)で作業しています。私のプロトコルのフライコマンドでは(メインスレッド上で実行されている)GUIが作成されます。新しいコマンドを作成するたびに、動的スタックに追加します。スレッド間のスタックの同期

(pthreadを使用して)別のスレッドでは、スタックにコマンドがあるかどうかを確認してから、ソケット(非ブロックbtw)を使ってプログレッシブに送信します。スタックの一番上にあるコマンドが送信されると、スタックをポップします(つまり、コマンドが削除され、最初の要素の下にある各コマンドがプッシュアップされます)。

私はそれを同期するのに大きな問題があると思います...私はいくつかのフラグ、ミューテックスを使用しようとしますが、私はいつもメモリ上でいくつかのアクセス違反で終わります。

基本的に何イムがやってはこれです:メインスレッドで

とき(IE)のユーザー押しボタン:別のスレッドで

char cmd[ 50 ] = "My new protocol command"; 

AppendCommandToSendStack(cmd); 

if(SendStackCount) 
{ 
    SendCommand(0); // 0 = The top of the stack. 

    if(IsCommandDoneSending(0)) 
    { 
      RemoveCommandFromStack(0); 
    } 
} 

誰も助けることができます私はこのメカニズムを動作させる方法を教えてくれます。あるいは、実装しようとしているImと同じまたは同様のワークフローをもたらすもう1つのアプローチ。

事前にTks!

[更新]

私はセマフォ上で読み始めると、私が必要なものを正確にthatsのだ...しかし、Imは擬似コードでやって何が...動作しているようですしません:

sem_t mutex; 

int stack_count; 

command *stack; 

main() 
{ 
    // Init & Connect client. 

    // Start Thread 

    sem_init(&lock_stack, 0, 1); 

    while(1) 
    { 
     sem_wait(&lock_stack); 

     ++stack_count; 

     stack = (command *) realloc(stack, stack_count * sizeof(command)); 

     strcpy(stack[ stack_count - 1 ].cmd, "new command"); 

     sem_post(&lock_stack); 
    } 
} 


thread() 
{ 
    while(1) 
    { 
     sem_wait(&lock_stack); 

     if(stack_count) 
     { 
      // Send stack[ 0 ].cmd via socket then when done pop the stack like this: 

      --stack_count; 

      if(0 < stack_count) 
      { 
       memcpy(&stack[ 0 ], 
        &stack[ 1 ], 
        (stack_count - 1) * sizeof(command)); 
      }   
     } 

     sem_post(&lock_stack); 
    } 
} 

これは基本的に新しいので、私はスタック配列上でランダムに発生するように見えるメモリアクセス違反があるため、何か明白なものがありません。

+1

ご質問いくつかの答えを受け入れることによって、あなたの受け入れの評価を向上させてください。また、 "*私はいくつかのフラグ、mutexを使用しようとしますが、私は常にメモリ上のアクセス違反で終わります。*"は非常に曖昧です。多分あなたはそれのためのいくつかのコードを提供することができますか? – Constantinius

+0

スタックエントリをカウントし、エントリがないときにプロデューサを待機させるセマフォだけでなく、mutexまたはCriticalSectionを使用して複数のアクセスからスタックを保護する必要があります。また、最初にスタックにゼロのアイテムがあるときに、セマフォカウントを1に初期化するのはなぜですか?ああ - そして、動的に割り当てられたオブジェクト/構造体へのポインタを積み重ねるだけで、そのrealloc/memcpyのものを取り除こうとします。スタックへの/からのrealloc/memcpyは、キューがmutexによってロックされている間に行われなければならない - 競合が悪い。 –

答えて

2

あなたは、プロデューサ - コンシューマの問題の古典的な例があります。あなたはproduceコマンドにしたい、他のスレッドはconsumeです。基本的な生産者 - 消費者の問題を実装する方法を説明しているhttp://en.wikipedia.org/wiki/Producer-consumer_problemを見ることができます。

0

簡単な解決策は次のようになります。

Thread 1 : 
     lock mutex 
     put items on stack 
     unlock mutex 


    Thread 2 : 
    loop 
     lock mutex 
     check item on stack 
     if somthing get item on stack 
     unlock mutex 

より効果soultionは次のようになります。

Thread 1 : 
     lock mutex 
     put items on stack 
     signal on conditionVariable 
     unlock mutex 

Thread 2 : 
     lock mutex 
     check item on stack 
     if none wait on conditionVariable 
     // here you will be woke up when there is a signal 
     get item on the stack 
     unlock mutex 
     do your work 
+0

あなたのより効果的な解決策にはデッドロックが含まれています。スレッド2が条件変数を待つとき、スレッド1はミューテックスを得ることができないので、それを通知します。条件変数を待っている間にスレッド2のmutexを一時的に解放する必要があります。 – smerlin

+0

うん、本当に2つのミューテックスがあるはずです。 1つは条件変数、1つはコンシューマ間の同期です。 – UmNyobe

+0

@smerlin:pthread条件変数APIが使用されていると仮定すると、wait APIはmutexを保持している間に呼び出されるように設計されています(スレッドをブロックする前に適切な時点でロックを解除します)。実際、mutexを保持していない状態で 'pthread_cond_wait()'を呼び出すのは誤りです。 –