Boost :: поток, перенасыщение и обмен данными - PullRequest
1 голос
/ 26 августа 2011

Я думаю, у меня проблема в моей программе. Я должен создать объект, который непрерывно взаимодействует с внешней системой слежения и получает от нее координаты точки. Я обернул этот класс внутри boost :: thread и перед первыми вызовами моего приложения Glut я создаю объект потока и отсоединяю его

Код для основных методов класса следующий

boost::mutex resourceMutex;

void Tracker::init()
{  
  boost::mutex::scoped_lock lock(resourceMutex);

  try
  {
    // some initializations
  }
  catch (std::bad_alloc const&)
  {  
     cerr << "Memory allocation fail during init!" << endl;
  }

  try
  {  
     p3dData = (Position3d*)calloc( NUM_MARKERS , sizeof( Position3d ) );
     if ( p3dData==NULL )
       throw std::bad_alloc();
  }
  catch ( std::bad_alloc const&)
  {  
     cerr << "Memory allocation fail during memory allocation!" << endl;
  }

}

void Tracker::update()
{
  boost::mutex::scoped_lock lock(optotrakResourceMutex);
  //... operations on vector< Eigen::Vector3d > points
}

vector<Eigen::Vector3d> &Tracker::getAllPoints()
{
  return points;
}

Мой glutTimerFunc выполняет вызов функции обновления, в которой каждый кадр выбирает точки с помощью метода getAllPoints, в то время как поток трекера непрерывно обновляет их (на самом деле частоты доступа к данным отличаются, поток обращается к ним быстрее Переполнение вызовов функций обновления.

Теперь, когда программа завершается, я сначала удаляю объект Tracker, выделенный с помощью new, а затем прерываю поток, содержащий его, но иногда я получаю странное поведение, я думаю, что это утечка памяти

Является ли способ получения данных с разными частотами доступа и использования scoped_lock правильным или я должен установить некоторую защиту в методе getAllPoints?

1 Ответ

1 голос
/ 27 ноября 2013

Я понимаю, что ваш выделенный поток отслеживания постоянно вызывает Tracker::update() для получения данных локализации с вашего устройства (NDI Optotrak?)

Затем ваше приложение OpenGL получает доступ к последним точкам через регулярный интервал из основного потока, используя Tracker::getAllPoints().

В этом случае вектор трехмерных точек Tracker::points является общим ресурсом между этими двумя потоками.

Чтобы предотвратить одновременный доступ, обе операции записи в update() и чтения с getAllPoints() должны быть защищены мьютексом, а не только записью, как в вашем текущем коде. Код чтения в основном потоке также должен блокировать мьютекс:

// In your main application:
void timerFunc()
{
    Tracker* tracker = ...;            // Obtain a pointer to the tracker object
    tracker->LockResourceMutex();      // Enter critical section
    vector< Eigen::Vector3d >& pointsRef = tracker->getAllPoints();
    //... operations on points, protected by the mutex
    tracker->UnlockResourceMutex();    // Leave critical section
}

// In class Tracker:
void Tracker::LockResourceMutex() { optotrakResourceMutex.lock(); }
void Tracker::UnlockResourceMutex() { optotrakResourceMutex.unlock(); }

Предупреждение: если ваши операции над точками в timerFunc() являются медленными, то мьютекс будет оставаться заблокированным в течение длительного времени, и ваш поток трекера заблокирует его при вызове Tracker::update().

Лучшим вариантом было бы изменить Tracker::getAllPoints(), чтобы он возвращал копию вектора трехмерных точек вместо ссылки:

// In class Tracker:
vector<Eigen::Vector3d> Tracker::getAllPoints()
{
    boost::mutex::scoped_lock lock(optotrakResourceMutex);
    return points; // Will call the std::vector() copy constructor
}

// In your main application:
void timerFunc()
{
    Tracker* tracker = ...;            // Obtain a pointer to the tracker object
    vector< Eigen::Vector3d > myPoints = tracker->getAllPoints();
    //... operations on your own copy if points
}

Обратите внимание, как мьютекс инкапсулирован в классе Tracker и как timerFunc() не нужно беспокоиться об этом.

Также обратите внимание, как мьютекс блокируется только во время копирования. Копия списка трехмерных векторов, безусловно, будет быстрее, чем математические операции с ними.

...