你真的能用WaitFor..等待条件变量吗..对象
Can you really wait on Condition Variable with WaitFor...Object(s)?
我正试图在许多CONDITION_VARIABLE
上实现某种等待
这里的答案意味着WaitForMultipleObjects
等在处理Windows API(以及互联网上的许多地方)时是有效的选项,但事实并非如此。
首先,MSDN文档中没有任何地方写到Windows Condition变量是WaitFor...
函数的有效参数
其次,WaitFor...
似乎只接受HANDLE
类型作为参数,这基本上是一个内核对象。但CCD_ 6并不是真正的CCD_
最后,尝试使用条件变量(同时作为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";
}
那么,你真的能等待一个条件变量吗?还是它只是一个城市传说?
我不这么认为,也没有任何意义。
首先,WaitForXxx
函数(主要)在调度器对象上运行,调度器对象是内核对象的子集,包括定时器、事件、互斥、信号、线程和进程(以及一些内部对象类型,如KAGTE
和KQUEUE
,但不包括访问令牌或文件映射对象),它们具有DISPATCHER_HEADER
。它肯定不会在内核不知道的用户模式结构上工作。
其次,请注意,当您在条件变量上休眠("等待")时,您必须使用正确的函数SleepConditionVariableCS
或SleepConditionVariableSRW
指定这是基于关键部分的条件变量还是基于SRWL的条件变量。因此,Windows(不仅仅是内核)不知道你要传递什么样的条件变量,但它需要这些信息才能正确运行。由于您没有向WaitForXxx
提供此信息,因此它们不能与条件变量一起使用。
问题的简单答案是否。不能将WaitForXxx
函数与Windows同步API提供的条件变量一起使用。来自链接文档:
条件变量是同步基元,使线程能够等待特定条件发生。条件变量是不能在进程之间共享的用户模式对象。
WaitForXxx
函数接受通用HANDLE
类型的参数,该类型表示内核对象的句柄。条件变量是用户模式对象,而不是内核的对象,因此不能将它们与这些函数一起使用,因为它们只能与内核对象一起使用。
此外,这些函数的文档非常明确地说明了它们可以等待哪些类型的对象,而条件变量不在该列表中。例如,WaitForMultipleObjects
说:
WaitForMultipleObjects
函数可以在lpHandles数组中指定以下任何对象类型的句柄:
- 更改通知
- 控制台输入
- 事件
- 内存资源通知
- Mutex
- 流程
- 信号量
- 螺纹
- 等待计时器
它们都有相同的列表,所以没有混淆。
从技术上讲(我们在这里深入讨论了未记录的实现细节,所以不应该把它当作福音),Win32WaitForSingleObject
和WaitForMultipleObjects
函数是基于内核子系统提供的KeWaitForSingleObject
和KeWaitForMultipleObjects
函数构建的。您可以将内核支持的对象划分为三个基本类别:调度器对象、I/O对象/数据结构和其他所有对象。第一类调度器对象是最低级别的对象,它们在主体中都使用相同的DISPATCHER_HEADER
数据结构来表示。Dispatcher对象是唯一可"等待"的对象类型。根据定义,正是这种DISPATCHER_HEADER
结构使对象可等待。如果使用此数据结构表示对象,则可以将其传递给内核同步函数。因此,相同的规则将适用于Win32函数。
整个问题似乎是基于Managu在回答中的一句话:"Windows发布了WaitForMultipleObjects,如果你愿意将代码限制为Windows同步原语,这可能是一个解决方案。">也许他不认为条件变量(因为它们是由Windows实现的)是同步原语,或者他只是错了。aJ的回答(他提到的)非常清楚地表明WaitForMultipleObjects
用于"等待多个内核对象",并且我们已经确定条件变量不是内核对象。无论哪种方式,我都看不到任何证据表明你可以做到这一点。
显然,不能将WaitForXxx
函数族与boost::condition_variable
、std::condition_variable
或其他任何函数一起使用。我相信你已经知道了,但你的问题让一些人感到困惑,因为它链接到了一个涉及Boost实现的问题。
我并不特别清楚为什么需要同时等待多个条件变量。我想您可以根据经典的Win32同步原语(如互斥体)编写自己的条件变量实现,然后使用WaitForMultipleObjects
等待。您可能可以在网上找到此类代码的示例,因为条件变量直到Vista才成为操作系统的一部分。例如,本文讨论了在Windows中实现条件变量的策略,因为它们是由POSIXPthreads规范定义的。您还可以研究使用事件对象。
- 基于模板值的条件变量
- 没有超时的C++条件变量
- 在条件变量中触发错误信号的频率是多少
- 在通知提升间处理条件变量时未按住锁会导致问题
- 通知条件变量后使用互斥锁
- 滥用条件变量
- 升压插值条件变量可以虚假唤醒吗?
- 子线程中的条件变量等待停止主线程中的执行
- 条件变量基本示例
- 正在连接的等待条件变量的线程会发生什么情况?
- C++11如何在1个线程中使用条件变量处理2个线程安全队列
- 当线程处理不同的类时,应该在哪里声明条件变量、互斥对象
- 为什么在同一条件变量上使用多个互斥锁会使此代码崩溃?
- 条件变量:wait_for.gcc错误
- 如何"stop"正在等待条件变量的分离线程?
- 如何杀死被条件变量锁定的线程?
- 使用互斥锁和条件变量作为成员时如何修复"use of deleted function"?
- C++ 多个使用者线程卡在条件变量上
- POSIX 条件变量和互斥体"竞争"
- 将cpp_redis pub/sub与条件变量一起使用时出现问题