boost :: mutex /如何测试互斥锁是否被锁定

时间:2009-12-15 01:35:13

标签: boost mutex

我知道,我知道,我的信息的标题可能看起来很挑衅,因为 boost :: mutex purposefuly不暴露锁定/解锁(为了避免死锁)。

然而,这些方面的提升文档非常简短(至少可以说),所以我想问是否有人可以在以下用例中帮助我。

假设你有一个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

的版本
//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完成吗?

谢谢!

3 个答案:

答案 0 :(得分:5)

如果您确实承诺在析构函数体中使用Lockable::lock(),则可以使用OnTimer()函数使用Lockable::try_lock(),并且只有在该函数返回true时才继续。如果OnTimer()首先启动,那么OnTimer()会将析构函数置于保持状态,但仍然无法解决析构函数运行,完成和释放互斥锁的问题,以及然后OnTimer()开始并成功抓取互斥锁。

这样的序列可能属于未定义的行为领域,但该诅咒不会阻止它发生。使用状态标志除了互斥锁 - 类似于我在上面的评论中所描述的 - 可以让你检测后一种情况并阻止OnTimer()做任何事情而不是阅读旗。但是,在某些时候,这只是将创可贴置于创可贴之上。

答案 1 :(得分:4)

@Seh:我完全同意这是代码味道,我应该(并且会)纠正根本原因。

然而,为了帮助任何遇到与我相同问题的人(即与增强文档作斗争),我试图实施你的建议。 下面的代码现在正确编译(虽然代码气味现在非常强大)

#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;
};

答案 2 :(得分:2)

互斥:: try_lock()