1

我认为我的程序有问题。我必须创建一个与外部跟踪系统持续通信并从中获取点坐标的对象。我将这个类包装在 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 方法选择点,而跟踪器线程不断更新它们(实际上访问数据的频率不同,线程调用比 glut 更新函数更快来电。

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

获取具有不同访问频率的数据和使用 scoped_lock 的方式是否正确,或者我应该在 getAllPoints 方法中设置一些保护措施?

4

1 回答 1

1

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

然后,您的 OpenGL 应用程序使用Tracker::getAllPoints().

在这种情况下,3D 点的向量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()为返回 3D 点向量的副本而不是参考:

// 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()不需要担心它。

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

于 2013-11-27T08:13:13.293 回答