0

I have a function and that is called at specific intervals. I need to check the time previously its called, and the current time. If the difference between the function call is 10 milliseconds then execute some piece of code. Sleep should not be used since some other things are executing in parallel. I have written the following code and the function is called at every 10 milliseconds but the difference i am calcuting is giving 1 or 2 milliseconds less sometimes. what is best way to calculate the difference?

fxn()
{
    int logCurTime;
    static int logPrevTime = 0, logDiffTime = 0;
    getCurrentTimeInMilliSec(&logCurTime);          

    if (logPrevTime > 0)
        logDiffTime += logCurTime - logPrevTime;

    if (logCurTime <= logPrevTime)
        return;

    if (logDiffTime >= 10)
    {
        ...
        ...
        logDiffTime = 0;
    }
    logPrevTime = logCurTime;
}

For eg: fxn is called 10 times with the interval of 10 milliseconds. some instance logDiffTime is just 8 or 9 and next instance it accounts the remaining time. i.e., 11 or 12.

Arun
  • 2,247
  • 3
  • 28
  • 51
  • 1
    can't you use alarm() and set the timer for desire period .Use your function as alarm handler . – SACHIN GOYAL Dec 29 '15 at 11:17
  • 2
    "*things are executing in parallel*" - if that is so, why not use sleep? – Stefan Falk Dec 29 '15 at 11:21
  • @StefanFalk - inside that function, i will have another condition to execute some piece f code at every 20 seconds. so if I use sleep then the other condition will affect – Arun Dec 29 '15 at 11:34
  • None of the suggested answers address Windows. – Thomas Dickey Dec 29 '15 at 11:49
  • @impulse that simply means that you execute that part of your code every 2nd time the thread wakes up. I don't get your point. – Stefan Falk Dec 29 '15 at 12:33
  • 1
    1 to 2 ms difference is well within the jittering you'll get on a normal operating system. Expect up to a few hundred ms once in a while when the OS decided to do other things for a while. You'll not get your 10ms predictably until you move to a real time operating system. – nos Dec 29 '15 at 12:38
  • impulse I think @nos is right: 2 ms is AFAIK a excellent deviation for a general purpose OS like linux. You won't get better results without saying goodbye to common operating systems and getting into the whole real time deal (special OS, many things to consider while designing your application, even saying goodbye to X86). – Superlokkus Dec 30 '15 at 01:24

3 Answers3

1

Using sleep() to get code executed in specific time intervals is indeed a bad idea. Register your function as the handler for a timer interrupt. Then it will be called very precisely on time.

If you're doing heavy lifting stuff in your function, than you should do it in another thread, because you will run into trouble when you're function is taking too long. (it will just be called from the beginning again).

In posix (linux) you could do it like this

#include <sys/time.h>
#include <stdio.h>
#include <signal.h>

if (signal (SIGALRM, fxn) == SIG_ERR)
    perror ("Setting your function as timer handler failed");
unsigned seconds = 42;//your time
struct itimerval old, new_time;
new_time.it_interval.tv_usec = 0;
new_time.it_interval.tv_sec = 0;
new_time.it_value.tv_usec = 0;
new_time.it_value.tv_sec = (long int) seconds;
if (setitimer (ITIMER_REAL, &new_time, &old) != 0)
    perror ("Setting the timer failed");

or in windows:

#include <Windows.h>

void Fxn_Timer_Proc_Wrapper(HWND,UINT,UINT_PTR,DWORD){
    fxn();
}

unsigned seconds = 42;//your time
UINT_PTR timer_id;
if ( (timer_id = SetTimer(NULL,NULL,seconds *1000,(TIMERPROC) Fxn_Timer_Proc_Wrapper) == NULL){
    //failed to create a timer
}
Superlokkus
  • 4,731
  • 1
  • 25
  • 57
0

It may not be exactly what you are looking for, however I feel it should be clarified: The sleep call only suspends the calling thread, not all threads of the process. Thus, you can still run parallel threads while one of them sleeps. See this question for more: Do sleep functions sleep all threads or just the one who call it?

For a solution to your problem you should register your function with a timer interrupt. See the other answer on how to do that.

Community
  • 1
  • 1
RunOrVeith
  • 4,487
  • 4
  • 32
  • 50
0

10ms is at the edge of what is achievable see stack overflow : 1ms timer . However, several suggestions on how to get 10ms did come out.

  1. timerfd_create allows your program to wait using select.
  2. timer_settime allows your program to request the 10ms interval.

The caveats on linux are :-

  1. May not be scheduled - the OS could be busy doing something else.
  2. May not be accurate - as 10ms appears to be the shortest interval that works, it may be +/- 1 or 2 ms.
Community
  • 1
  • 1
mksteve
  • 12,614
  • 3
  • 28
  • 50