2017-08-31 5 views
0

私の実装に欠陥があり、わかりません。私は一貫してコールバックを呼び出して、 "m_bufferLatest"という名前のバッファに書き込むワーカースレッドを持っています。バッファをコピーする必要があり、メインスレッドでのコピーを完了するまでに時間がかかります。だから私は "m_bufferLatest"を保護する必要があります。したがって、メインスレッドでContinuousCapture()を呼び出すと、コールバックがm_bufferLatestに書き込まれないように、「m_skipFrame」というフラグを設定します。複数のスレッドを使用するバッファの保護方法を教えてください。

私のプログラムを実行すると、m_bufferLatestはワーカースレッドの実行速度に応じてnullになります。

誰かが私のプログラムに間違っていることを教えてもらえますか?

bool HandleEofCallbackCont() 
{ 
    std::lock_guard<std::mutex> lock(m_EofMutex); 

    if (!m_skipFrame) { 
     //here update m_bufferCont 
     if (!m_camera->SaveLatestFrameToQueue()) 
     { 
      printf("get latest frame failed.. \n"); 
     } 

    } 

     m_EofFlag = true; 
    } 
    m_EofCond.notify_one(); 

    return true; 
} 

bool ContinuousCapture(Settings settings) 
{ 
    //wait for the condition variable otherwise timeout 
    std::unique_lock<std::mutex> lock(m_EofMutex); 
    { 
     if (!m_EofFlag) 
     { 
      m_EofCond.wait_for(lock, std::chrono::seconds(10), [&]() { 
       return (m_EofFlag); 
      }); 
     } 

     m_skipFrame = true; 

     int size = m_camera->m_bufferBytes/sizeof(uns16); 

     //transfer from data 
     if (!TransferData(settings, (uns16*)m_camera->m_bufferLatest, size, m_Frame)) 
     { 
      printf("transfer data failed"); 
      return false; 
     } 

     m_skipFrame = false; 
     m_EofFlag = false; 
    } 

    return true; 
} 

これは私がやろうとしていることです。

+1

すぐに出ることの1つは、mutexがロックされているときにm_skipframeが設定されていて、mutexの外側でチェックされていることです。 – SergeyA

+0

もう一つは、転送が失敗した場合でも、フラグはまだtrueです。これ以上の書き込みは行われません。また、mutexロックの下でEofCondを待っています。この場合、他のスレッドが何をすると思いますか?バッファを保護し、フラグをアトミックにするためにのみ、ミューテックスを使用します。 –

+0

@SergeyA m_skipFrameをミューテックス内に移動しましたが、それでも動作しません。私は無効なアクセスメモリを取得します。私はコードを更新しました。 – user1296153

答えて

0

2つのスレッドを同期させるには、同期プリミティブを使用することが非常に重要です。また、mutexによってシステムがロックされる時間を短縮する。 mutexは異なるスレッド間で保証された状態を可能にしますが、パフォーマンスはシングルスレッドのパフォーマンスに向いています。

m_SkipFrame = true; 

つのスレッドに表示されますが、interthread-happens-beforeのいくつかのフォームは、他のスレッドが動作していないことを確認するために発生する必要があります。

std::atomic<> is a good mechanism, for testing state between the threads. 

あなたは1つのリーダーと1つのライターしか持っていないとします。次のスキームは最も簡単に動作します。

  1. バッファをカプセル化するクラスを作成します。このクラスは、ライターからリーダーに情報を渡すために使用されます。
  2. インタラクションクラスでこのポインタを使用しますが、std :: atomicに格納してください。
  3. 完成したポインタをリーダまたはライタのいずれかに廃棄します。

バッファを保持するクラスを仮定します。

スレッド間のクラス内で次に
class BufferHolder { 
}; 

class Interthread { 
    std::atomic<BufferHolder*> m_Exchange; 
} 

その後ライターが....

void Interthread::Writer(BufferHolder * pNewBuffer) { 
    BufferHolder * oldBuffer = m_Exchange.exchange(pNewBuffer); 
    delete oldBuffer; // may be nullptr, but that is ok. 
    // if the oldBuffer wasn't used, it was sort of wasted. 
} 

BufferHolder * Interthread::Reader() { 
    BufferHolder * pNewBuffer = m_Exchange.exchange(nullptr); 
    return pNewBuffer; 
} 

だろうあなたは、固定を格納するキュー、またはいくつかのメカニズムを持っている必要があるかもしれませんバッファ数。

関連する問題