当OwningThread表示线程ID时,它为什么是HANDLE类型的CRITICAL_SECTION的成员
Why is the OwningThread member of CRITICAL_SECTION of type HANDLE, when it is denoting the thread ID?
我试图为CRITICAL_SECTION解锁代码添加一些调试检查,并尝试了以下操作:
...
if (m_pCritSect) {
ASSERT(m_pCritSect->OwningThread == GetCurrentThreadId());
LeaveCriticalSection(m_pCritSect);
}
}
通过调试CRITICAL_SECTIONS(使用VS 2005,主要在WindowsXP上),我"知道"OwningThread
(winnt.h
中定义的RTL_CRITICAL_SECTION
结构的成员)的值是持有锁的线程的thID的值。
然而,线程ID由DWORD
(unsigned long
的typedef)值表示,而此变量的类型为HANDLE
(void*
的typedef),需要和的reinterpret_cast
,使用basetsd.h
中的HandleToULong
宏才能使上述代码工作。
甚至MSDN文档也声明:
当第一个线程调用EnterCriticalSection例程时,(…)OwningThread将成为调用方的线程ID。
那么,为什么这被定义为HANDLE
呢?
编辑注意:我发现了一个声明,其中海报表明HANDLE/DWORD Id不匹配是一些Windows内部的一些已知错误功能。也许这里也有这种情况:
GetCurrentThreadId返回一个DWORD,我在消息PsLookupThreadByThreadId获取HANDLE中的线程Id。。。…
这是一个已知的Windows API错误(在我与相关的筛选器管理器DEV,如filter中所示由于I/O Manager API问题,管理器也是如此。)只要你没有超过5亿左右的线程和进程(它们使用一个共享句柄表),你会没事的。也许到那时这是一个真正的问题,我们将运行一些不同的东西。[RE:威胁要处理64位?,08年8月8日14:21,Tony Mason]
SDK中任何名称以RTL或RTL开头的标识符都是运行时层的代码或声明,是将有充分文档记录的Winapi与无文档记录的本机操作系统api结合在一起的粘合剂。winapi是铁板一块的,本机操作系统随着每个Windows版本的发布而发生重大变化。不可避免的是,胶水也会发生变化。
winapi是有文档的层,本机操作系统是没有文档的。运行时层也没有文档,但随着时间的推移,它的一部分被暴露了出来。要么是因为它重新填充了winapi中缺少的功能。或者,在这种情况下,因为它对解决问题真正有用。然而,这样做的一个核心问题是,一旦声明被披露,微软就再也无法改变它了。因为这样做会破坏现有的程序,给客户带来很大的负担。
毫无疑问,ThreadOwner字段曾经在以前的Windows版本中真正拥有线程的句柄。请注意LockSemaphore是如何误导的,它实际上是一个自动重置事件。太迟了,修不好了,猫出包了。
我认为主要原因是它是一个实现细节。如果在历史上的某个时候,它真的是一个把手或类似的东西,我不会感到惊讶。
此外,我强烈建议不要在生产代码中使用内部成员,我并不是唯一一个这样做的人。如果仔细观察,同步API使用CRITICAL_SECTION
,而不是RTL_CRITICAL_SECTION(类型定义为CRITICAL_SECTION)
存储在OwningThread
成员中的值取自线程信息块的CLIENT_ID部分。在CLIENT_ID中,它被建模为PVOID,这可能是它在CRITICAL_SECTION:中以相同方式建模的原因
typedef struct _CLIENT_ID
{
PVOID UniqueProcess;
PVOID UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- <Windows>为什么 std::thread::native_handle 返回类型为"long long unsigned int"的值,而不是 void*(又名 HANDLE)?
- 在 Linux C++ 中,HANDLE 的数据类型可能是什么
- 当OwningThread表示线程ID时,它为什么是HANDLE类型的CRITICAL_SECTION的成员