Timer

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
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.
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?
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.