我有一个具有wait
函数的类,它等待队列被填满。一旦队列非空,则通知condition_variable
,等待功能清空队列并处理其元素。
我想在单元测试中验证此wrapper::wait
调用(检查队列是否为空)实际上阻塞了线程。我有一个atomic_bool
的片状设置,它在等待调用之后设置,并且天真地认为执行以下序列会起作用。
wait
的函数创建线程,然后设置atomic_bool
。atomic_bool
是否具有开始值atomic_bool
。有两个缺失的同步点:两个"验证"不能保证在我希望它们发生时:
atomic_bool
。有没有办法解决此问题,而无需添加一个或多个额外的condition_variables
/ mutexes
来同步操作?
答案 0 :(得分:0)
测试这种情况的一种方法是在等待之前和之后添加一些跟踪或日志行。最后,您将比较跟踪或跟踪文件以及一些参考,以查看是否按预期发生了这些活动。
答案 1 :(得分:0)
这确实是使用std::condition_variable
的完美方案,但无论如何:您可以使用多个同步点和std::atomic<int> gate
。各种值将编码测试的不同阶段。等待超过某个恒定时间 T 的值将被视为测试用例失败 1 。
gate == 0
:未初始化辅助线程。gate == 1
:初始化了辅助线程,但它还没有响应。gate == 2
:初始化并运行的辅助线程,可以假定已调用wait
。gate == 3
:主线程已向队列添加了一些内容,辅助线程仍可能正在等待。gate == 4
:辅助线程退出wait
并设置最后一个值。如果您愿意,可以省略几个同步点。
gate
设为0。gate
设为1。gate
成为2;失败时:&#34;辅助线程从未到达wait
&#34; 。gate
设置为3。gate
变为4;失败时:&#34;辅助线程从未退出wait
&#34; 。gate
变为1;失败&#34;产卵后主线程挂起&#34; 。gate
设为2.致电wait
。wait
退出;队列已处理完毕。)gate
成为3;失败&#34;回到过去&#34; 。gate
设为4并退出。实施&#34;等待和检查&#34;部分您可以使用compare_exchange
和std::chrono
。可能的实现可能是这样的:
#include <atomic>
#include <chrono>
#include <condition_variable>
std::cv_status wait_till_reaches(
std::atomic<int> &gate,
std::chrono::high_resolution_clock::duration const &rel_time,
const int desired_value,
bool increment = false
) {
const int next_value = desired_value + (increment ? 1 : 0);
int dummy = desired_value;
const std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
while (not gate.compare_exchange_weak(dummy, next_value)) {
dummy = desired_value;
if ((std::chrono::high_resolution_clock::now() - start) >= rel_time) {
return std::cv_status::timeout;
}
}
return std::cv_status::no_timeout;
}
1 这不是完全测试您的代码是否正常工作,而是 ,但是另一方面,如果你有一些线程问题,不能保证测试用例也能捕获它(在某些时候你必须决定等待响应的时间)。