Timer

Jun 20, 2010 at 10:30am
I made Timer class that i couldn't find for a long time. Dunno if its right place but I thought I'll share, maybe someone will find it useful.
If you've got some ideas of improvements please share :)
Timer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef TIMER_H
#define TIMER_H
#include <sys/time.h>

class Timer
{
    public:
        Timer(unsigned int Delay, void (*pToFunction)(Timer* timer));
        ~Timer();
        bool Probe();
        bool Probe(timeval& SomeTime); //could be useful if there're 1000 timers in row
        void Start() { isActive=true;}
        void Stop() { isActive=false;}
        bool IsActive() { return isActive; }
        void SetDelay(unsigned int Delay) { itsDelay=Delay; }
    protected:
    private:
        unsigned int itsDelay;
        bool isActive;
        timeval itsStart;
        void (*itspToFunction)(Timer*);
};

#endif // TIMER_H 


Timer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include "Timer.h"

Timer::Timer(unsigned int Delay, void (*pToFunction)(Timer* timer))
        :itsDelay(Delay),itspToFunction(pToFunction),isActive(true)
{
    gettimeofday(&itsStart,0);
}

Timer::~Timer()
{
    itspToFunction=0;
}

bool Timer::Probe()
{
    timeval CurrentTime;
    gettimeofday(&CurrentTime,0);
    if(isActive==false || itsDelay > ((CurrentTime.tv_sec-itsStart.tv_sec)*1000 + (CurrentTime.tv_usec-itsStart.tv_usec)/1000))
    {
        return false;
    }
    else
    {
        itspToFunction(this);
        gettimeofday(&itsStart,0);
        return true;
    }
}
bool Timer::Probe(timeval& SomeTime)
{
    if(isActive==false || itsDelay > ((SomeTime.tv_sec-itsStart.tv_sec)*1000 + SomeTime.tv_usec-itsStart.tv_usec/1000))
    {
        return false;
    }
    else
    {
        itspToFunction(this);
        gettimeofday(&itsStart,0);
        return true;
    }
}


Sample code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include "../Timer.h"
using namespace std;

void Test(Timer* timer)
{
    static int i = 0;
    i++;
    cout << "Test nr. " << i << endl;
    if(i>5)timer->Stop();
}
int main()
{

    Timer test(2250,Test);
    while(test.IsActive())test.Probe();

}
Last edited on Jun 20, 2010 at 10:32am
Jun 21, 2010 at 3:49am
I would use a boost::function instead of a C-style function pointer for the callback.

I do not understand what a "probe" operation is on a timer.
Jun 21, 2010 at 6:21am
probe is used to check if timeout is reached, i couldn't think of better way to do that. In my sample code it is checked in endless loop.
What's wrong with pointer to function?
Jun 21, 2010 at 9:06am
you could use the POSIX threads real time clock.

http://www.kernel.org/doc/man-pages/online/pages/man2/timer_settime.2.html

it works in seconds and nanoseconds.

It invokes a transparent threaded callback.
here is a really scruffy C program I was playing with a while back.
it calls a callback which printfs and tots up the timer overruns, which are timer intervals missed.
enter a milliseconds delay. 1 millisecond will start to overrun.

I was going to do something with it one day.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <time.h>
#include <sys/time.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
/*
**   NOTE NOTE NOTE NOTE
**
**	you will need to link: (use LDFLAGS)
**
**	-lrt -lpthread
*/

#define SZ 46
long int overruns[SZ];

void callback(union sigval  arg) {

    timer_t * p =  (timer_t *) arg.sival_ptr;;
    int delay = timer_getoverrun(*p);
    printf("delay = %d\n", delay);

    // count overruns, which are timer intervals skipped
    if (delay<SZ) {
	overruns[delay]++;
    } else {
	timer_delete(*p);
	return ;
    }

    return;
}

timer_t timerid;
int main (int argc, char ** argv) {

    struct sigevent se;
    struct itimerspec ts;
    long int nsec;
    long int msec;
    long int sec;

    if(argc<2) {
	fputs("time milliseconds?\n",stderr);
	exit(1);
    }
    msec = atoi(argv[1]);
    fprintf(stderr, "got  %ld\n", msec);
    sec = (msec / 1000); 
    msec %= 1000;
    nsec = msec * 1e06;;

    se.sigev_notify = SIGEV_THREAD;
    se.sigev_value.sival_ptr = &timerid;
    se.sigev_notify_function = callback;
    se.sigev_notify_attributes = NULL;

    if ( -1 == timer_create(CLOCK_REALTIME, &se, &timerid)) {
	perror("timer_create:");
	return(1);
    }

    ts.it_value.tv_sec = sec;
    ts.it_value.tv_nsec = nsec;
    ts.it_interval.tv_sec = sec;
    ts.it_interval.tv_nsec = nsec ;
    printf("nanosex = %ld\n", ts.it_interval.tv_nsec);
    printf("seconds = %ld\n", ts.it_interval.tv_sec);

    if (-1 == timer_settime(timerid, 0, &ts, NULL)) {
	perror("timer_settime:");
    }
    getchar();   // press a key to stop

    int t;
    for(t=0; t<SZ; t++) {

	printf("overruns[%02d] = %ld\n", t, overruns[t]);
    }


    return 0;
}

Topic archived. No new replies allowed.