C++ 设置C+中while循环的执行速率+;实时同步代码

C++ 设置C+中while循环的执行速率+;实时同步代码,c++,synchronization,while-loop,C++,Synchronization,While Loop,我正在使用.cpp源代码进行实时模拟。我必须每0.2秒(200ms)采集一次样本。。。有一个while循环,它会在每一步中提取一个样本。。。我想同步这个while循环的执行,以便每(200ms)获取一个样本。。。如何修改while循环 while (1){ // get a sample every 200 ms } 除非您使用的是实时操作系统,否则您的问题很棘手 但是,Boost有一个支持您所需内容的库。(但是,不能保证每隔200毫秒就会有人给你打电话

我正在使用
.cpp
源代码进行实时模拟。我必须每0.2秒(200ms)采集一次样本。。。有一个while循环,它会在每一步中提取一个样本。。。我想同步这个while循环的执行,以便每(200ms)获取一个样本。。。如何修改while循环

while (1){
          // get a sample every 200 ms
         }

除非您使用的是实时操作系统,否则您的问题很棘手

但是,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;
}
//
//timer.cpp
// ~~~~~~~~~
//
//版权所有(c)2003-2012克里斯托弗·M·科尔霍夫(克里斯在科尔霍夫网站)
//
//根据Boost软件许可证1.0版发布。(参见随附的
//文件LICENSE_1_0.txt或复制到http://www.boost.org/LICENSE_1_0.txt)
//
#包括
#包括
#包括
int main()
{
boost::asio::io_服务io;
boost::asio::deadline_timer t(io,boost::posix_time::seconds(5));
t、 等待();

std::cout要获得绝对感知几乎是不可能的-可能是在嵌入式系统中。但是,如果您只需要一个近似的频率,您可以使用chrono库(如
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 );
}
while(1){
系统时钟::时间点现在=系统时钟::现在();
自动持续时间=now.time_-since_-epoch();
自动启动_millis=std::chrono::duration_cast(duration).count();
//运行样本
现在=系统时钟::现在();
duration=now.time_-since_-epoch();
自动结束_millis=std::chrono::duration_cast(duration).count();
自动睡眠时间=最大值(0,200-(结束时间-开始时间));
std::this_线程::sleep_for(sleep_for);
}

提供的答案向您展示了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
         }
现在,您只需要为
SIGALRM
安装一个不做任何事情的信号处理程序,代码就完成了

您可以按照链接查看

如果在程序执行过程中可能触发多个信号,那么与其依赖中断的系统调用,不如阻止
SIGALRM
处理程序以确定的方式唤醒的内容。一种可能性是在一个管道。然后,信号处理程序可以写入该管道的写入端

void sigalarm_handler (int)
{
    if (write(alarm_pipe[1], "", 1) != 1) {
        char msg[] = "write: failed from sigalarm_handler\n";
        write(2, msg, sizeof(msg)-1);
        abort();
    }
}
按照链接查看。

#包括
#包括
#包括
int main(){
std::线程计时器\u线程;
while(true){
计时器线程=标准::线程([]){
std::this_thread::sleep_for(std::chrono::seconds(1));
});
//做事

std::cout使用
std::this_thread::sleep_
:

#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);
    }
}

它需要精确到什么程度?199.99-200.01或195-205可以接受吗?除了每200ms执行一次外,您还需要做多少工作?您是在实时系统上还是在普通计算机上执行此操作?将此周期精确到200ms是不可能的。您需要告诉我们您的错误阈值以及您使用的操作系统。使用
gettimeofday(2)
ualarm(3)
(POSIX的一部分,应该在任何地方都可以使用)或
usleep(3)
(这仅限于Linux,AFAIK)。但是要小心,信号处理程序可以做的事情非常有限,请参见
signal(7)
。最好将所有内容都保存在std::chrono类型中,而不是执行一系列到基本类型的转换。有关使用std::chrono的更好方法,请参见下面的另一个答案:使用
std::this_thread::sleep_until()而不是计算时间增量
,每次按固定的时间间隔递增绝对唤醒时间。对于解决方案如何解决问题,一些解释可能会有用。问题是如何使循环中的一段代码以固定的时间间隔执行。最简单的实现是简单地睡眠一定时间,例如200毫秒。但是如果你正在做一些需要时间的事情,那么下一次迭代将在该时间之后开始。解决方案是让第二个线程进行休眠,而不执行,这样它将保持一个恒定的间隔,与你想要在循环中运行的代码无关。嗨,Howard。看起来chrono_io.h功能已经被移动了到“date.h”。因此,您可以删除头文件。200ms替换为std::chrono::millizes(200)。因此,该行应为…next+=std::chrono::millizes(200)。C++14中引入了
200ms
语法。
void sigalarm_handler (int)
{
    if (write(alarm_pipe[1], "", 1) != 1) {
        char msg[] = "write: failed from sigalarm_handler\n";
        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;
}
#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);
    }
}
200ms
205ms
200ms
195ms
205ms
198ms
202ms
199ms
196ms
203ms
...