我有一个维护一个列表的对象。 其中一个辅助方法需要
清理操作从另一个线程的列表中删除对象,因此需要locking其中的列表。
这个工作正常,只要助手没有调用已经存在的列表的锁,那么解锁操作实际上不会允许其他线程访问列表,所以我想在这种情况下标记一个错误。
据我了解, CRITICAL_SECTION
API不提供官方支持的方式来查询当前进程是否持有这个对象,所以我正在考虑“hack-ish”方法(毕竟,这是一个debugging帮助,而不是打算进入生产代码):
变种1是检查CRITICAL_SECTION
结构的OwningThread
字段,但我想知道是否有保证这个字段是
GetCurrentThreadId()
结果相同的数字空间中的线程ID 变种2是lockingCRITICAL_SECTION
,然后检查RecursionCount
; 这假定recursion计数器具有固定的起始值。
有没有什么我错过了,我可以用它来构build一个有点面向未来的(也就是说,它将在一行代码中打破,这个代码行接近我解释的所有注释)assertion statement that the current thread is 不是某个CRITICAL_SECTION
的持有者?
让你自己的关键部分,提供这样的功能。 在你的调试版本中使用它。 在发布版本中,使用常规关键部分。
一个简单的方法是使用两个关键部分和一个所有者字段。 获得这样的作品:
获得第一关键部分。
获得第二个关键部分。
将所有者设置为此线程。
发布第二个关键部分。
发布工作是这样的:
获得第二个关键部分。
将所有者设置为无。
发布第一个关键部分。
发布第二个关键部分。
断言如下所示:
获得第二个关键部分。
断言所有者不是这个线程。
发布第二个关键部分。
更新 :上面有一个错误。 它错误地处理了这种情况:锁定,锁定,解锁,断言我们没有关键部分,但是我们这样做。 解决办法可能是保持“锁定计数”。 锁定计数不必将CS设置为“无主”。 如果锁定计数为零,则它是无主的。 所以断言路径“无主或所有者不是这个线程”。
我使用这样的东西
class CriticalSection { private: CRITICAL_SECTION section_; unsigned int owning_thread_id_; unsigned int lock_count_; public: CriticalSection() { InitializeCriticalSection(§ion_); owning_thread_id_ = 0; lock_count_ = 0; } ~CriticalSection() { DeleteCriticalSection(§ion_); } void enter() { EnterCriticalSection(§ion_); owning_thread_id_ = GetCurrentThreadId(); lock_count_ ++; } void leave() { if( GetCurrentThreadId() == owning_thread_id_ ) { lock_count_ --; if( lock_count_ == 0 ) owning_thread_id_ = 0; } LeaveCriticalSection(§ion_); } bool tryEnter() { if( TryEnterCriticalSection(§ion_)) { 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_; } };