我试图在许多CONDITION_VARIABLE
上实施某种等待。
The answers here意味着在处理Windows API(以及互联网上的更多地方)时,WaitForMultipleObjects
等是有效选项,但似乎并非如此。
首先,在MSDN文档中没有写到Windows Condition变量是WaitFor...
函数的有效参数。
其次,WaitFor...
似乎只接受HANDLE
类型作为参数,它基本上是一个内核对象。但是PCONDITION_VARIABLE
实际上不是HANDLE
最后,尝试使用条件变量(作为PCONDITION_VARIABLE
和未记录的CONDITION_VARIABLE::Ptr
)使函数返回错误代码6(无效句柄)
例如:
CONDITION_VARIABLE cv;
InitializeConditionVariable(&cv);
auto res = WaitForSingleObject(cv.Ptr, INFINITE); //returns immediately
if (res != WAIT_OBJECT_0) {
auto ec = GetLastError();
std::cout << ec << "\n";
}
所以,你真的可以等待一个条件变量,还是只是一个都市传奇?
答案 0 :(得分:5)
您的问题的简单答案是否。您不能将WaitForXxx
函数与Windows同步API提供的condition variables一起使用。来自链接文档:
条件变量是同步原语,它使线程能够等到特定条件发生。条件变量是不能跨进程共享的用户模式对象。
WaitForXxx
函数接受通用HANDLE
类型的参数,该类型表示内核对象的句柄。条件变量是用户模式对象,而不是内核对象,因此您不能将它们与这些函数一起使用,因为它们仅适用于内核对象。
此外,这些函数的文档非常清楚它们可以等待哪些类型的对象,并且条件变量不在该列表中。例如,WaitForMultipleObjects
说:
WaitForMultipleObjects
函数可以指定 lpHandles 数组中以下任何对象类型的句柄:
- 更改通知
- 控制台输入
- 事件
- 内存资源通知
- 互斥
- 过程
- 信号量
- 发
- 等待计时器
他们都有相同的清单,所以没有混淆。
从技术上讲(我们在这里深入研究未记录的实现细节,所以你不应该依赖它作为福音),Win32 WaitForSingleObject
和WaitForMultipleObjects
函数建立在{{1内核子系统提供的{}和KeWaitForSingleObject
函数。您可以将内核支持的对象划分为三个基本类别:调度程序对象,I / O对象/数据结构以及其他所有类别。第一类调度程序对象是最低级别的对象,它们都在其主体中使用相同的KeWaitForMultipleObjects
数据结构表示。 Dispatcher对象是“可等待”的唯一对象类型。根据定义,正是这个DISPATCHER_HEADER
结构使对象可以等待。如果使用此数据结构表示对象,则可以将其传递给内核同步函数。因此,相同的规则将适用于Win32函数。
整个问题似乎是基于Managu在his answer中做出的一个声明:“Windows已将WaitForMultipleObjects作为aJ发布,如果您愿意将代码限制为Windows同步原语。“也许他不认为条件变量(因为它们是由Windows实现的)是同步原语,或者他可能是错的。他引用的aJ的答案非常明确地指出DISPATCHER_HEADER
用于“等待多个内核对象”,并且我们已经确定条件变量不是内核对象。无论哪种方式,我都没有看到任何有关“城市传说”的证据,你可以做到这一点。
显然,您无法将WaitForMultipleObjects
系列函数与WaitForXxx
或boost::condition_variable
或其他任何内容一起使用。我相信你已经知道了,但是你的问题让一些人感到困惑,因为它链接到一个引用Boost实现的问题。
我不清楚为什么你需要同时等待多个条件变量。我猜你可以编写自己的条件变量实现,基于经典的Win32同步原语,例如互斥,你可以等待std::condition_variable
。您可以在线找到此类代码的示例,因为在Vista之前,条件变量不会成为操作系统的一部分。例如,this article讨论了在Windows中实现条件变量的策略,因为它们是由POSIX Pthreads规范定义的。您还可以考虑使用Event Objects。
答案 1 :(得分:5)
我不这么认为,这没有任何意义。
首先,WaitForXxx
函数(主要)在调度程序对象上运行 - 内核对象的一个子集,包括定时器,事件,互斥体,sempahores,线程和进程(以及一些内部对象类型,如{{1具有KAGTE
的s和KQUEUE
s,但不能访问令牌或文件映射对象)。它肯定不会在内核不知道的用户模式构造上工作。
其次,请注意当您在条件变量上睡眠(&#34;等待&#34;)时,您必须使用正确的函数指定这是基于关键部分的条件变量还是基于SRWL的条件变量 - DISPATCHER_HEADER
或SleepConditionVariableCS
。所以,Windows(不仅是内核)不知道你传递了什么样的条件变量,但它需要这些信息才能正常运行。由于您未向SleepConditionVariableSRW
提供此信息,因此它们不能与条件变量一起使用。