简单的线程计时器,请检查是否正常
Simple threaded timer, sanity check please
我制作了一个非常简单的线程计时器类,考虑到MT代码的缺陷,我想进行一次健全性检查。这里的想法是启动一个线程,然后连续循环等待一个变量。如果等待超时,则超过了间隔,我们调用回调。如果变量被发出信号,线程应该退出,我们不调用回调。
我不确定的一件事是,考虑到线程可能在那里(只是)是可连接的,我的代码在析构函数中会发生什么。我可以加入析构函数中的线程以确保它完成吗?
这是课程:
class TimerThreaded
{
public:
TimerThreaded() {}
~TimerThreaded()
{
if (MyThread.joinable())
Stop();
}
void Start(std::chrono::milliseconds const & interval, std::function<void(void)> const & callback)
{
if (MyThread.joinable())
Stop();
MyThread = std::thread([=]()
{
for (;;)
{
auto locked = std::unique_lock<std::mutex>(MyMutex);
auto result = MyTerminate.wait_for(locked, interval);
if (result == std::cv_status::timeout)
callback();
else
return;
}
});
}
void Stop()
{
MyTerminate.notify_all();
}
private:
std::thread MyThread;
std::mutex MyMutex;
std::condition_variable MyTerminate;
};
我想一个更好的问题可能是请某人给我指一个非常简单的线程计时器,如果某个地方已经有了。
我可以加入析构函数中的线程以确保它完成吗?
不仅可以,而且这样做很常见。如果线程实例在销毁时是可连接的(即仍在运行),则会调用terminate
。
由于某种原因,结果总是超时。它似乎从未得到信号,因此从未停止。这是正确的吗?notify_all是否应该取消阻止wait_fo?
只有当线程当时正好在cv上时,它才能解除阻止。您可能要做的是在线程开始运行并开始等待之前(或者可能在callback
运行时)调用Start
,然后立即调用Stop
。在这种情况下,线程将永远不会得到通知。
您的代码存在另一个问题。在某些实现中,即使您没有显式调用notify_X
,阻塞的线程也可能被错误地唤醒。这会导致你的计时器在没有明显原因的情况下随机停止。
我建议您添加一个标志变量,指示是否已调用Stop
。这将解决上述两个问题。这是使用条件变量的典型方式。我甚至为你写了代码:
class TimerThreaded
{
...
MyThread = std::thread([=]()
{
for (;;)
{
auto locked = std::unique_lock<std::mutex>(MyMutex);
auto result = MyTerminate.wait_for(locked, interval);
if (stop_please)
return;
if (result == std::cv_status::timeout)
callback();
}
});
....
void Stop()
{
{
std::lock_guard<std::mutex> lock(MyMutex);
stop_please = true;
}
MyTerminate.notify_all();
MyThread.join();
}
...
private:
bool stop_please = false;
...
有了这些变化,你的计时器应该可以工作,但要意识到"[std::condition_variable::wait_for
]可能会因为调度或资源争用延迟而阻塞超过timeout_duration",用cppreference.com的话说。
如果某个地方已经有线程计时器的话,请给我介绍一个非常简单的线程计时器。
我不知道标准的c++解决方案,但现代操作系统通常提供这种功能,或者至少提供可以用来构建它的部分。请参阅linux上的timerfd_create获取示例。
- 检查是否以特定精度给出双精度
- 地图计数确实很重要,或者只是检查是否存在
- 检查是否安装了 windows10 C++
- 模板化检查是否存在带有参数列表的类成员函数?
- 如何巧妙地编写两个函数——一个用于检查是否存在解决方案,另一个用于获取所有解决方案
- MPI:检查是否有任何进程已终止
- 给定一个大小为 N 的数组 S,检查是否可以将序列拆分为两个序列
- Vulkan 的传输队列系列功能和显卡支持:条件检查是否准确?
- 如何检查是否定义了固定宽度的整数
- 使用预处理指令检查是否包含标头?
- 在预处理器中检查 g++ 是否使用 -fopenmp 调用
- 将字符串转换为整数类型T,检查是否存在溢出
- C++编译时检查是否可以用某种类型的参数调用重载函数
- 检查是否至少设置了一点而不跳跃
- 在if条件下,右或左改变值的相等性检查是否有任何区别
- C++ 检查是否按下了键,而不是按住了
- 如何在 c++ 中解析包含整数的字符串并检查是否大于最大值
- 检查是否为质数大o
- 检查是否需要 utf8 转换并转换为 utf8
- 如何正确检查 c++ 是否存在注册表项?