首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何根据固定的周期频率正确地协调线程?

如何根据固定的周期频率正确地协调线程?
EN

Stack Overflow用户
提问于 2015-07-10 00:27:33
回答 1查看 363关注 0票数 0

我想创建一个网关来传递来自can总线和lcm的消息,反之亦然。如果lcm中的消息以特定频率发送,则其在can总线上的副本应以完全相同的频率发送。

你将如何解决这个问题?

在我的脑海中,我考虑了两个线程,一个用于一个方向,在一个循环中将消息从一个系统转换到另一个系统。这两个线程由定时器协调,该定时器被设置为远低于可能的最大消息传递频率的频率。计时器在每个周期后向线程发送信号。线程在每个循环结束时等待该事件,即它们休眠并释放资源,直到事件发生。我已经实现了这个想法,但是产生的频率并不是恒定的。我是不是在概念上做错了什么?

解决方案应该在windows上运行,因此例如使用本地windows api或boost线程。网关应该是实时的。

EN

回答 1

Stack Overflow用户

发布于 2015-07-10 02:08:12

对于windows,可以使用timeSetEvent以固定的时间间隔设置事件,尽管MSDN将其列为过时函数。timeSetEvent的替代品使用回调函数,因此您必须在回调函数中设置事件。

您可以使用timeBeginPeriod将滴答率从默认的64 to == 15.625 ms增加到1 ms

一些游戏有以固定频率运行的线程,并在当前周期中有足够的延迟时间时轮询高频计数器和睡眠。为防止漂移,延迟基于高频计数器的原始读数。与Windows XP兼容的示例代码,其中睡眠(1)可能需要2毫秒。dwLateStep是一种辅助诊断工具,如果代码超过周期,则会递增。

代码语言:javascript
运行
复制
/* code for a thread to run at fixed frequency */
typedef unsigned long long UI64;        /* unsigned 64 bit int */
#define FREQ    400                     /* frequency */
DWORD    dwLateStep;                    /* late step count */
LARGE_INTEGER liPerfFreq;               /* 64 bit frequency */
LARGE_INTEGER liPerfTemp;               /* used for query */
UI64 uFreq = FREQ;                      /* process frequency */
UI64 uOrig;                             /* original tick */
UI64 uWait;                             /* tick rate / freq */
UI64 uRem = 0;                          /* tick rate % freq */
UI64 uPrev;                             /* previous tick based on original tick */
UI64 uDelta;                            /* current tick - previous */
UI64 u2ms;                              /* 2ms of ticks */
UI64 i;

    /* ... */ /* wait for some event to start thread */
    QueryPerformanceFrequency(&liPerfFreq);
    u2ms = ((UI64)(liPerfFreq.QuadPart)+499) / ((UI64)500);

    timeBeginPeriod(1);                 /* set period to 1ms */
    Sleep(128);                         /* wait for it to stabilize */

    QueryPerformanceCounter((PLARGE_INTEGER)&liPerfTemp);
    uOrig = uPrev = liPerfTemp.QuadPart;

    for(i = 0; i < (uFreq*30); i++){
        /* update uWait and uRem based on uRem */
        uWait = ((UI64)(liPerfFreq.QuadPart) + uRem) / uFreq;
        uRem  = ((UI64)(liPerfFreq.QuadPart) + uRem) % uFreq;
        /* wait for uWait ticks */
        while(1){
            QueryPerformanceCounter((PLARGE_INTEGER)&liPerfTemp);
            uDelta = (UI64)(liPerfTemp.QuadPart - uPrev);
            if(uDelta >= uWait)
                break;
            if((uWait - uDelta) > u2ms)
                Sleep(1);
        }
        if(uDelta >= (uWait*2))
            dwLateStep += 1;
        uPrev += uWait;
        /* fixed frequency code goes here */
        /*  along with some type of break when done */
    }

    timeEndPeriod(1);                   /* restore period */
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31323214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档