断言当前线程不保存CRITICAL_SECTION锁

我有一个维护一个列表的对象。 其中一个辅助方法需要

  • locking列表
  • find第一个元素
  • 解锁列表
  • 通知另一个线程开始清理操作
  • 等待另一个线程完成
  • 重复这个,直到列表为空。

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

这个工作正常,只要助手没有调用已经存在的列表的锁,那么解锁操作实际上不会允许其他线程访问列表,所以我想在这种情况下标记一个错误。

据我了解, CRITICAL_SECTION API不提供官方支持的方式来查询当前进程是否持有这个对象,所以我正在考虑“hack-ish”方法(毕竟,这是一个debugging帮助,而不是打算进入生产代码):

变种1是检查CRITICAL_SECTION结构的OwningThread字段,但我想知道是否有保证这个字段是

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

变种2是lockingCRITICAL_SECTION ,然后检查RecursionCount ; 这假定recursion计数器具有固定的起始值。

有没有什么我错过了,我可以用它来构build一个有点面向未来的(也就是说,它将在一行代码中打破,这个代码行接近我解释的所有注释)assertion statement that the current thread is 不是某个CRITICAL_SECTION的持有者?

让你自己的关键部分,提供这样的功能。 在你的调试版本中使用它。 在发布版本中,使用常规关键部分。

一个简单的方法是使用两个关键部分和一个所有者字段。 获得这样的作品:

  1. 获得第一关键部分。

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

  3. 将所有者设置为此线程。

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

发布工作是这样的:

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

  2. 将所有者设置为无。

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

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

断言如下所示:

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

  2. 断言所有者不是这个线程。

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

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

我使用这样的东西

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