Boost ::线程,过剩和数据共享

时间:2011-08-26 19:31:31

标签: multithreading boost mutex glut scoped-lock

我认为我的程序存在问题。 我必须创建一个与外部跟踪系统连续通信的对象,并从中获取点的坐标。 我把这个类包装在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选择点,而跟踪器线程继续更新它们(实际上访问数据的频率不同,线程调用的速度比过剩功能调用。

现在当程序退出时,我首先删除用new分配的Tracker对象,然后中断包含它的线程,但有时我会得到奇怪的行为,我认为它们是内存泄漏

获取具有不同访问频率的数据和使用scoped_lock的方法是正确的,还是应该在getAllPoints方法中加入一些保护?

1 个答案:

答案 0 :(得分:1)

我了解您的专用跟踪器线程会不断调用Tracker::update()从您的设备获取本地化数据(NDI Optotrak?)

然后,您的OpenGL应用程序使用Tracker::getAllPoints()从主线程定期访问最新的点。

在这种情况下,3D点Tracker::points的向量是这两个线程之间的共享资源。

为了防止并发访问,update() 中的写入操作和<{em>}的读取必须受到互斥锁的保护,而不仅仅是当前代码中的写入。主线程中的读取代码也必须锁定互斥锁:

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()以返回3D点向量的副本而不是引用:

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如何不必担心它。

另请注意互斥锁仅在复制期间如何锁定。 3D矢量列表的副本肯定会比对它们的数学运算更快。