我认为我的程序存在问题。 我必须创建一个与外部跟踪系统连续通信的对象,并从中获取点的坐标。 我把这个类包装在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方法中加入一些保护?
答案 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矢量列表的副本肯定会比对它们的数学运算更快。