1

スレッドセーフな Q を使用して、バッファ内に乱数を生成しています。メインの glWidget プログラムでは、バッファーの内容を DeQ し、画面を更新する必要があります。

#ifndef CONCURRENTQUEUE_H
#define CONCURRENTQUEUE_H

#include <QByteArray>
#include <QQueue>
#include <QMutex>

class ConcurrentQueue
{
private:
    unsigned short segments[360][100];

public:
    ConcurrentQueue();
    void InitSegments();
    void Enqueue(int i, int j, unsigned short value);
    unsigned short Dequeue(int i, int j);

    bool isEmpty();
private:
    QMutex mutex;
};

#endif // CONCURRENTQUEUE_H

ConcurrentQueue::ConcurrentQueue()
{
    InitSegments();
}

void ConcurrentQueue::InitSegments()
{
    for(int i = 0; i < 360; i++)
        for(int j = 0; j < 100; j++)
        {
            segments[i][j] = 0;
        }
}

void ConcurrentQueue::Enqueue(int i, int j, unsigned short value)
{
    mutex.lock();
    segments[i][j] = value;
    mutex.unlock();
}
unsigned short ConcurrentQueue::Dequeue(int i, int j)
{
    unsigned short color = 0;
    mutex.lock();
    color = segments[i][j];
    mutex.unlock();

    return color;
}

GenerateBuffer クラス:

#ifndef GENERATEBUFFERS_H
#define GENERATEBUFFERS_H

#include <QThread>   
#include "thread_safe/concurrentqueue.h"

class GenerateBuffers : public QThread
{
public:
    GenerateBuffers();

    void run();

    int rounds;
    int segmentIndex;    
};

#endif // GENERATEBUFFERS_H

#include "generatebuffers.h"    
#include <time.h>

ConcurrentQueue segmentsQueue;  
GenerateBuffers::GenerateBuffers()
{
    segmentIndex = 1;   
    run();
}

void GenerateBuffers::run()
{
    while(true)
    {
        int angleIndex = segmentIndex * 23;

        for(int i = angleIndex - 23; i < angleIndex; i++)
            for(int j = 0; j < 100; j++)
            {
                unsigned short randNumber = rand() % 255;

                segmentsQueue.Enqueue(i, j, randNumber);
            }

        if(segmentIndex > 16)
        {
            segmentIndex = 0;
        }
        else
        segmentIndex++;

        usleep(150);
    }
}

generateBuffers .cpp ファイルに ConcurrentQ のインスタンスを作成しました

ConcurrentQueue segmentsQueue;

そして、glWidget ヘッダー ファイルで次のように宣言しました。

そして、私はそれを次のように使用しました:

    ppi->highlight(j, i, segmentsQueue.Dequeue(i, j));

実行するとプログラムが終了します。スレッドセーフな実装が正しいかどうかわかりません。コードについての意見を教えてください。

4

1 に答える 1

1

ここで問題を推測しようとして、最も単純なものであるインデックス境界を試しました。したがって、run() メソッドで、segmentIndex を 16 にバインドしようとしています。想像してみてください。

  segmentIndex == 16

そして今、ループの中に

  if(segmentIndex > 16)   // segmentIndex == 16, (16 > 16) is false
  {
    segmentIndex = 0;
  }
  else
  { // we go that way
    segmentIndex++;   // segmentIndex gets 17
  }

次のループ実行で

  // segmentIndex is 17
  int angleIndex = segmentIndex * 23;   // 17 * 23 == 391

  for(int i = angleIndex - 23; i < angleIndex; i++)   // i = [368,391)
  {
    for(int j = 0; j < 100; j++)
    {
      unsigned short randNumber = rand() % 255;

      // unsigned short segments[360][100];
      segmentsQueue.Enqueue(i, j, randNumber);    
      // enqueue doesn't check index, causes crash
    }
  }

したがって、コードは機能しません。この種の問題を回避するために、コードでマジック ナンバー (360、100、23、16) を使用しないでください。
ところで、問題を簡単にデバッグできたはずです。

また、このコードはおそらくあなたが思っていることをしません

GenerateBuffers::GenerateBuffers()
{
    segmentIndex = 1;   
    run();
}

run() は同じスレッドで呼び出されます。あなたはおそらくstart()代わりに欲しかった

于 2013-06-10T09:04:28.480 に答える