设置C++代码中while循环的执行速率以进行实时同步
setting the execution rate of while loop in a C++ code for real time synchronization
我正在使用.cpp
源代码进行实时模拟。我必须每0.2秒取样一次(200 ms)。。。有一个while循环,它在每一个时间步骤中都会获取一个样本。。。我想同步这个while循环的执行,以每隔(200 ms)获得一个样本。。。我应该如何修改while循环?
while (1){
// get a sample every 200 ms
}
使用std::this_thread::sleep_until
:的简单准确的解决方案
#include "date.h"
#include <chrono>
#include <iostream>
#include <thread>
int
main()
{
using namespace std::chrono;
using namespace date;
auto next = steady_clock::now();
auto prev = next - 200ms;
while (true)
{
// do stuff
auto now = steady_clock::now();
std::cout << round<milliseconds>(now - prev) << 'n';
prev = now;
// delay until time to iterate again
next += 200ms;
std::this_thread::sleep_until(next);
}
}
延迟部分不需要"date.h"
。它提供了round<duration>
函数(现在在C++17中),并使打印duration
s变得更容易。这一切都在"做事情"之下,对循环延迟无关紧要。
只要得到一个chrono::time_point
,再加上你的延迟,然后一直睡到time_point
。只要你的"东西"比你的延迟花费的时间少,你的循环平均会忠于你的延迟。不需要其他线程。不需要定时器。只有<chrono>
和sleep_until
。
这个例子只是为我输出:
200ms
205ms
200ms
195ms
205ms
198ms
202ms
199ms
196ms
203ms
...
除非您使用的是实时操作系统,否则您的问题很棘手。
不过,Boost有一个库可以支持您想要的内容。(然而,不能保证你每200毫秒就会接到一次电话。
Boost ASIO库可能就是你想要的,这里是他们教程中的代码:
//
// timer.cpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
t.wait();
std::cout << "Hello, world!n";
return 0;
}
链接在这里:链接以促进asio。
你可以把这个代码,像这个一样重新排列
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
boost::asio::io_service io;
while(1)
{
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
// process your IO here - not sure how long your IO takes, so you may need to adjust your timer
t.wait();
}
return 0;
}
下一页还有一个异步处理IO的教程。
提供的答案表明Boost中有一些工具可以帮助您实现这一点。我最近的产品演示了如何使用setitimer()
,这是一种用于迭代定时器的POSIX工具。
你基本上需要这样的改变:
while (1){
// wait until 200 ms boundary
// get a sample
}
使用迭代计时器,激发的信号将中断任何阻塞的信号调用。所以,你可以永远阻止一些事情。select
会做得很好:
while (1){
int select_result = select(0, 0, 0, 0, 0);
assert(select_result < 0 && errno == EINTR);
// get a sample
}
要为每200毫秒建立一个间隔计时器,请使用setitimer()
,传入适当的间隔。在下面的代码中,我们将间隔设置为200毫秒,其中第一个从现在起激发150毫秒。
struct itimerval it = { { 0, 200000 }, { 0, 150000 } };
if (setitimer(ITIMER_REAL, &it, 0) != 0) {
perror("setitimer");
exit(EXIT_FAILURE);
}
现在,您只需要为SIGALRM
安装一个什么都不做的信号处理程序,代码就完成了。
您可以按照链接查看完整的示例。
如果在程序执行期间可能触发多个信号,那么与其依赖于中断的系统调用,不如阻止SIGALRM
处理程序可以以确定性的方式唤醒的东西。一种可能性是在管道的读取端的read
上具有while
循环块。然后,信号处理程序可以写入该管道的写入端。
void sigalarm_handler (int)
{
if (write(alarm_pipe[1], "", 1) != 1) {
char msg[] = "write: failed from sigalarm_handlern";
write(2, msg, sizeof(msg)-1);
abort();
}
}
按照链接查看完整的示例。
#include <thread>
#include <chrono>
#include <iostream>
int main() {
std::thread timer_thread;
while (true) {
timer_thread = std::thread([](){
std::this_thread::sleep_for (std::chrono::seconds(1));
});
// do stuff
std::cout << "Hello World!" << std::endl;
// waits until thread has "slept"
timer_thread.join();
// will loop every second unless the stuff takes longer than that.
}
return 0;
}
要获得绝对的洞察力几乎是不可能的——也许在嵌入式系统中。然而,如果您只需要一个近似的频率,那么使用std::chrono
(c++11)或boost::chrono
等计时库可以获得相当不错的性能。像这样:
while (1){
system_clock::time_point now = system_clock::now();
auto duration = now.time_since_epoch();
auto start_millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
//run sample
now = system_clock::now();
duration = now.time_since_epoch();
auto end_millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
auto sleep_for = max(0, 200 - (end_millis - start_millis ));
std::this_thread::sleep_for( sleep_for );
}
- 松弛原子与无同步情况下的记忆连贯性
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- 在C++中同步线程
- 与 stdio 同步是否使程序 I/O 非交互式?
- 使用专用显卡进行 OpenGL 渲染时帧速率较低
- 如何在qt中同步应用程序和显示器的刷新率?
- Windows 进程间同步类似事件?
- 在打开多个其他窗口时使用全屏窗口时帧速率非常低
- 当对套接字 send() 的同步调用由于连接另一端丢失而被阻止时,如何恢复?
- 将 10 个线程与原子布尔值同步
- libcurl :显示正在运行的上传和下载速率
- ofstream::close() 是否在 Linux 上调用同步?
- 与Visual Studios(c ++)同步时如何组织github存储库?
- 原子获取是否与互斥锁释放同步?
- Boost (Beast) websocket:同步写入挂起
- Postgres vs MySQL:命令不同步;.
- 如何在IQualProp::get_AvgFrameRate中重置帧速率?
- 为什么当通过 TCP 发送的消息速率增加时,请求-响应消息对的延迟会降低?
- 同步两个具有不同帧速率的传感器
- 设置C++代码中while循环的执行速率以进行实时同步