2009-12-15 135 views
9

我知道,我知道,我的消息的标题可能看起来具有挑衅性,因为 boost :: mutex有意义地不公开锁定/解锁(为了避免死亡锁)。boost :: mutex /如何测试一个互斥锁是否被锁定

但是这些方面的boost文档很短(至少可以这么说),所以我在问以下用例是否有人能帮助我。

假设你有一个类Foo,其中有:
- 析构函数,需要一些时间来完成
- 一个由独特的线程调用的方法,但破坏过程中不应该叫

class Foo 
{ 
public: 

    virtual ~Foo() 
    { 
    //Time consuming operations here 
    } 


    //Method called by a timer belonging to a distinct class 
    void OnTimer() 
    { 
    //Other time consuming stuff. Should not be called during destruction ! 
    } 


}; 

我尝试(没有成功),以实现基于增强版本::互斥

//boost::mutex implementation 
class Foo 
{ 
public: 
    Foo() 
    { 
    } 

    virtual ~Foo() 
    { 
    { 
     boost::mutex::scoped_lock lock(mDisposingMutex); 
     //Time consuming operations here 
    } 
    } 


    //Method called by a timer belonging to a distinct class 
    void OnTimer() 
    { 
    { 
     //Imaginary code here: mutex::locked() method is private !!! 
     if (! mDisposingMutex.locked()) 
     return; 
    }  
    //Other time consuming stuff. Should not be called during destruction ! 
    } 

private: 
    boost::mutex mDisposingMutex; 
}; 

我完全错了吗?任何人都可以告诉我,这应该怎么做与boost :: mutex?

谢谢!

+0

为什么被破坏你的对象,而另一个线程仍然有一个指针指向它? – 2009-12-15 01:38:28

+0

不直接回答问题,你可以取消注册引发'OnTimer()'调用作为你的析构函数的第一步吗?诚然,呼叫仍然可以通过“同时”异步进行,但尚不清楚为什么此对象正在遭受破坏仍然是这些回调的目标。 – seh 2009-12-15 01:40:30

+0

@Anon:同意,这是一种代码味道。尽管如此,我仍然对这个答案感兴趣。 @ Seh:您的评论基于相同的代码气味。但是,我不能直接取消它,而不会破坏封装。 – 2009-12-15 01:44:58

回答

5

如果您还承诺在析构函数体使用Lockable::lock(),你可以有你的OnTimer()功能使用Lockable::try_lock(),并继续仅当函数返回true。如果OnTimer()首先启动,但它仍然没有解决析构函数运行,完成和释放互斥锁,然后OnTimer()启动并成功地获取互斥体的问题,将有OnTimer()搁置析构函数。

这样的一个序列可能在未定义的行为领域,但是这种诅咒不会阻止它发生。除了互斥体之外,使用状态标记- 类似于我在上面的注释中描述的 - 可以让您检测到后一种情况,并停止执行除标记之外的任何操作。然而,在某些时候,这只是将创可贴置于创可贴之上。

2

互斥:: try_lock()

+0

如果您是锁定互斥锁的人,则返回false。 – 2015-11-04 15:20:47

4

@ Seh:我完全同意这是一种代码异味,我应该(也将会)纠正根本原因。

但是,为了帮助任何遇到与我一样的问题的人(即与boost文档打架),我试图实现您的建议。 现在下面的代码编译正确(尽管代码味道是现在非常强)

#include <boost/thread/mutex.hpp> 

//boost::mutex implementation 
class Foo 
{ 
public: 
    Foo() : 
    mIsDisposing(false) 
    { 
    } 

    virtual ~Foo() 
    { 
    { 
     boost::try_mutex::scoped_try_lock lock(mDisposingMutex); 
     if (! lock.locked()) 
     { 
     //Die by horrible death, or wait before trying again... 
     } 
     else 
     { 
     mIsDisposing = true; 
     } 
     //Time consuming operations here 
    } 

    } 


    //Method called by a timer belonging to a distinct class 
    void OnTimer() 
    { 
    { 
     boost::try_mutex::scoped_try_lock lock(mDisposingMutex); 
     if (! lock.locked() || mIsDisposing) 
     { 
     return;  
     } 
    }  
    //Other time consuming stuff. Should not be called during destruction ! 
    } 

private: 
    boost::try_mutex mDisposingMutex; 
    bool mIsDisposing; 
};