2011-08-26 57 views
1

我觉得我的程序有问题。 我必须创建一个连续与外部跟踪系统进行通信并从中获取点坐标的对象。 我包该类一个boost ::线程内,首先调用到我的转运蛋白的应用之前,我创建线程对象,我取下它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选取点,而跟踪器线程连续更新它们(实际上,对数据的访问频率不同,线程调用的速度比大量更新函数调用。

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

是获取不同频率访问和scoped_lock的使用是否正确,或者我应该在getAllPoints方法中加入一些防范措施?

+2

你确实在删除一个线程可能仍在访问的对象,或者我读错了吗? – ergosys

+0

是的,但我的问题是,如果线程在程序中的某个时刻调用exit(0)时会删除它...否则,在这种情况下删除对象并停止线程的正确方法是什么?线程析构函数是否处理包含对象的析构函数? 在我看来,我有不同的行为,如果我使用退出(0)或_exit(0)... – linello

+0

您的代码片段有错误:'init()'函数返回一些东西,但被声明为返回void。您使用不同名称的互斥锁。当你编辑你的实际代码时,首先检查它是否正确 –

回答

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矢量列表的副本肯定会比他们的数学运算更快。