断言当前线程不包含CRITICAL_SECTION锁

时间:2012-02-15 09:22:30

标签: windows multithreading winapi critical-section

我有一个维护列表的对象;

需要帮助方法之一
  • 锁定列表
  • 找到第一个元素
  • 解锁列表
  • 通知另一个线程开始清理操作
  • 等待另一个线程完成
  • 重复此操作直到列表为空。

清理操作从另一个线程中删除列表中的对象,因此需要锁定列表。

这个工作正常,只要没有调用已经保持的列表上的锁,因此解锁操作实际上不允许其他线程访问列表,所以我想在此标记错误情况下。

据我所知,CRITICAL_SECTION API没有提供官方支持的方式来查询当前进程是否包含此对象,所以我正在考虑“hack-ish”方法(毕竟,它是一个调试辅助工具,不打算进入生产代码):

变体1是检查OwningThread结构的CRITICAL_SECTION字段,但我想知道是否保证此字段是

  • 始终包含与GetCurrentThreadId()结果
  • 相同的数字空间中的线程ID
  • 在任何线程获取锁定时始终更新
  • 当我自己的线程释放锁时,
  • 总是被清除

变体2是锁定CRITICAL_SECTION,然后检查RecursionCount;这假设递归计数器具有固定的起始值。

我是否有任何我可以用来建立一个有点面向未来的东西(也就是说,它会在我所解释的所有评论附近的代码行中大声破解)断言声明当前线程某个CRITICAL_SECTION的持有者?

2 个答案:

答案 0 :(得分:2)

制作您自己的关键部分,提供此类功能。在调试版本中使用它。在发布版本中,使用常规临界区。

一种简单的方法是使用两个关键部分和一个所有者字段。获得的工作方式如下:

  1. 获取第一个关键部分。

  2. 获取第二个关键部分。

  3. 将所有者设置为此主题。

  4. 发布第二个关键部分。

  5. 发布的工作原理如下:

    1. 获取第二个关键部分。

    2. 将所有者设为无。

    3. 发布第一个关键部分。

    4. 发布第二个关键部分。

    5. Assert的工作原理如下:

      1. 获取第二个关键部分。

      2. 断言所有者不是这个主题。

      3. 发布第二个关键部分。

      4. 更新:上面有一个错误。它错误地处理了这种情况:锁定,锁定,解锁,断言我们没有关键部分,但我们这样做。修复可能是为了保持“锁定计数”。您不必使用锁定计数将CS设置为“无主”。如果锁定计数为零,则它是无主的。所以断言路径“无主或所有者不是这个线程”。

答案 1 :(得分:1)

我使用类似的东西

class CriticalSection
{
private:
  CRITICAL_SECTION section_;
  unsigned int owning_thread_id_;
  unsigned int lock_count_;

public:
  CriticalSection() 
  {
    InitializeCriticalSection(&section_);
    owning_thread_id_ = 0;
    lock_count_ = 0;

  }
  ~CriticalSection()
  {
    DeleteCriticalSection(&section_);
  }

  void enter()
  {
    EnterCriticalSection(&section_);
    owning_thread_id_ = GetCurrentThreadId();
    lock_count_ ++;
  }
  void leave()
  {

    if(  GetCurrentThreadId() == owning_thread_id_ )
    {
      lock_count_ --;
      if( lock_count_ == 0 )
        owning_thread_id_ = 0;
    }

    LeaveCriticalSection(&section_);
  }

  bool tryEnter() 
  { 
    if( TryEnterCriticalSection(&section_))
    {
      owning_thread_id_ = GetCurrentThreadId();
      lock_count_ ++;
      return true;
    }
    return false;
  }

  bool isCurrentThreadEntered()
  {
    return GetCurrentThreadId() == owning_thread_id_;
  }

  int getLockCount() { return lock_count_; }
  unsigned int getOwningThreadID() { return owning_thread_id_; }

};