How to coordinate threads properly based on a fixed cycle frequency?

后端 未结 1 1349
逝去的感伤
逝去的感伤 2021-01-27 18:58

I want to create a gateway to pass messages from a can bus and lcm and vice-versa. If a message in lcm is sent at a specific frequency, its copy on the can bus should be sent at

相关标签:
1条回答
  • 2021-01-27 19:21

    For windows, timeSetEvent can be used to set an event at a regular interval, although MSDN lists it as an obsolete function. The replacement for timeSetEvent uses a callback function, so you'd have to set an event in the callback function.

    You can increase the tick rate from it's default 64hz == 15.625 ms down to 1 ms using timeBeginPeriod

    Some games have threads that run at fixed frequencies, and poll a high frequency counter and Sleep when there's enough delay time remaining in the current cycle. To prevent drift, the delay is based off an original reading of the high frequency counter. Example code that is Windows XP compatible, where a Sleep(1) can take up to 2 milliseconds. dwLateStep is a diagnostic aid and incremented if the code exceeds a cycle period.

    /* 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 */
    
    0 讨论(0)
提交回复
热议问题