parent
8e1dbfa569
commit
03627c0ed5
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef TIMER_HPP
|
||||||
|
#define TIMER_HPP
|
||||||
|
|
||||||
|
#include <signal.h> // sigset_t
|
||||||
|
#include <time.h> // timer_t
|
||||||
|
|
||||||
|
class Timer
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Timer(const int signal = SIGALRM );
|
||||||
|
|
||||||
|
|
||||||
|
virtual void timerExpired() {}
|
||||||
|
|
||||||
|
virtual void periodicTimerExpired() {}
|
||||||
|
|
||||||
|
|
||||||
|
void createTimer(const time_t interval_sec,
|
||||||
|
const long interval_nsec = 0,
|
||||||
|
const time_t initExpr_sec = 0,
|
||||||
|
const long initExpr_nsec = 0);
|
||||||
|
|
||||||
|
void wait();
|
||||||
|
|
||||||
|
void stopTimer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int m_signal;
|
||||||
|
struct sigaction m_sigAction;
|
||||||
|
timer_t m_timerId;
|
||||||
|
bool m_periodic;
|
||||||
|
bool m_running;
|
||||||
|
|
||||||
|
}; // class Timer
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TIMER_HPP
|
@ -0,0 +1,88 @@
|
|||||||
|
#include "Timer.hpp"
|
||||||
|
|
||||||
|
#include "Common.hpp"
|
||||||
|
|
||||||
|
#include <signal.h> // sigset_t
|
||||||
|
// #include <assert.h> // assert
|
||||||
|
#include <time.h> // timer_t
|
||||||
|
// #include <errno.h> // EINVAL, EAGAIN, EINTR
|
||||||
|
// #include <set>
|
||||||
|
#include <string.h> // strerror
|
||||||
|
// #include <iostream>
|
||||||
|
// #include <stdio.h>
|
||||||
|
|
||||||
|
Timer::Timer(const int signal)
|
||||||
|
: m_signal(signal)
|
||||||
|
, m_periodic(false)
|
||||||
|
, m_running(true)
|
||||||
|
{
|
||||||
|
TRACE;
|
||||||
|
|
||||||
|
m_sigAction.sa_flags = SA_SIGINFO;
|
||||||
|
sigemptyset(&m_sigAction.sa_mask);
|
||||||
|
sigaddset( &m_sigAction.sa_mask, m_signal );
|
||||||
|
sigaction( m_signal, &m_sigAction, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Timer::createTimer(const time_t interval_sec,
|
||||||
|
const long interval_nsec,
|
||||||
|
const time_t initExpr_sec,
|
||||||
|
const long initExpr_nsec)
|
||||||
|
{
|
||||||
|
TRACE;
|
||||||
|
|
||||||
|
// create timer
|
||||||
|
struct sigevent sigev;
|
||||||
|
sigev.sigev_notify = SIGEV_SIGNAL;
|
||||||
|
sigev.sigev_signo = m_signal;
|
||||||
|
sigev.sigev_value.sival_ptr = &m_timerId;
|
||||||
|
if ( timer_create( CLOCK_MONOTONIC, &sigev, &m_timerId ) == -1 ) {
|
||||||
|
// std::cout << "Error from timer_create: " << strerror(errno) << std::endl;
|
||||||
|
LOG ( Logger::FINEST, "Error from timer_create: " /*strerror(errno)*/ );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// arm it
|
||||||
|
struct itimerspec its;
|
||||||
|
its.it_value.tv_sec = interval_sec;
|
||||||
|
its.it_value.tv_nsec = interval_nsec;
|
||||||
|
its.it_interval.tv_sec = initExpr_sec;
|
||||||
|
its.it_interval.tv_nsec = initExpr_nsec;
|
||||||
|
|
||||||
|
if ( initExpr_sec != 0 or initExpr_nsec != 0 ) m_periodic = true;
|
||||||
|
|
||||||
|
if ( timer_settime( m_timerId, 0, &its, 0 ) == -1 ) {
|
||||||
|
// std::cout << "Error from timer_settime: " << strerror(errno) << std::endl;
|
||||||
|
LOG ( Logger::FINEST, "Error from timer_settime: " /*strerror(errno)*/ );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Timer::wait()
|
||||||
|
{
|
||||||
|
TRACE;
|
||||||
|
|
||||||
|
int sig;
|
||||||
|
sigwait( &m_sigAction.sa_mask, &sig );
|
||||||
|
timerExpired();
|
||||||
|
if ( m_periodic ) {
|
||||||
|
while ( m_running ) {
|
||||||
|
sigwait( &m_sigAction.sa_mask, &sig );
|
||||||
|
periodicTimerExpired();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Timer::stopTimer()
|
||||||
|
{
|
||||||
|
TRACE;
|
||||||
|
|
||||||
|
struct itimerspec its;
|
||||||
|
its.it_value.tv_sec = 0;
|
||||||
|
its.it_value.tv_nsec = 0;
|
||||||
|
timer_settime( m_timerId, 0, &its, 0 );
|
||||||
|
m_running = false;
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
#include <cxxtest/TestSuite.h>
|
||||||
|
|
||||||
|
#include "Fixture.hpp"
|
||||||
|
|
||||||
|
// #define private public // reach TimerThread's private multimap
|
||||||
|
|
||||||
|
#include "Timer.hpp"
|
||||||
|
|
||||||
|
// #include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TestTimer : public CxxTest::TestSuite
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
class DummyTimer : public Timer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
DummyTimer(int maxPeriodicCount = 5)
|
||||||
|
: m_counter(0)
|
||||||
|
, m_maxPeriodicCount(maxPeriodicCount)
|
||||||
|
{
|
||||||
|
TRACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void timerExpired()
|
||||||
|
{
|
||||||
|
TRACE;
|
||||||
|
m_counter += 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void periodicTimerExpired()
|
||||||
|
{
|
||||||
|
TRACE;
|
||||||
|
static int count = 0;
|
||||||
|
m_counter++;
|
||||||
|
count++;
|
||||||
|
if ( count >= m_maxPeriodicCount ) {
|
||||||
|
stopTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int m_counter;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
int m_maxPeriodicCount;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void testBasic( void )
|
||||||
|
{
|
||||||
|
TEST_HEADER;
|
||||||
|
|
||||||
|
DummyTimer t;
|
||||||
|
t.createTimer(2);
|
||||||
|
t.wait();
|
||||||
|
TS_ASSERT_EQUALS( t.m_counter, 100 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void testBasicPeriodic( void )
|
||||||
|
{
|
||||||
|
TEST_HEADER;
|
||||||
|
|
||||||
|
DummyTimer t;
|
||||||
|
t.createTimer(2,0,1);
|
||||||
|
t.wait();
|
||||||
|
TS_ASSERT_EQUALS( t.m_counter, 105 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
Loading…
Reference in new issue