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


i want create gateway pass messages can bus , lcm , vice-versa. if message in lcm sent @ specific frequency, copy on can bus should sent @ exact same frequency.

how solve this?

in mind thought 2 threads, 1 each direction converting message 1 system in loop. 2 threads coordinated timer set frequency lower maximum message passing frequency possible. timer sents signal threads after each cycle. threads wait event @ end of each loop, i.e. sleep , free resources until event occures. implemented idea resulting frequencies not constant. doing conceptually wrong?

a solution should run on windows, utilize either native windows api or boost threads example. gateway should real-time capable.

for windows, timesetevent can used set event @ regular interval, although msdn lists obsolete function. replacement timesetevent uses callback function, you'd have set event in callback function.

you can increase tick rate it's default 64hz == 15.625 ms down 1 ms using timebeginperiod

some games have threads run @ fixed frequencies, , poll high frequency counter , sleep when there's enough delay time remaining in current cycle. prevent drift, delay based off original reading of high frequency counter. example code windows xp compatible, sleep(1) can take 2 milliseconds. dwlatestep diagnostic aid , incremented if code exceeds cycle period.

/* code thread run @ 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 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 event start thread */     queryperformancefrequency(&liperffreq);     u2ms = ((ui64)(liperffreq.quadpart)+499) / ((ui64)500);      timebeginperiod(1);                 /* set period 1ms */     sleep(128);                         /* wait stabilize */      queryperformancecounter((plarge_integer)&liperftemp);     uorig = uprev = liperftemp.quadpart;      for(i = 0; < (ufreq*30); i++){         /* update uwait , urem based on urem */         uwait = ((ui64)(liperffreq.quadpart) + urem) / ufreq;         urem  = ((ui64)(liperffreq.quadpart) + urem) % ufreq;         /* wait 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 type of break when done */     }      timeendperiod(1);                   /* restore period */ 

Comments