Timer refactored

master
Denes Matetelki 13 years ago
parent ac8409c59e
commit 4bfa4165ff

@ -2,7 +2,6 @@
#define TIMER_HPP
#include <signal.h> // sigset_t
#include <time.h> // timer_t
#include <map>
@ -29,18 +28,22 @@ public:
virtual ~Timer();
timer_t createTimer( TimerUser *m_timerUser,
clockid_t clockId = CLOCK_MONOTONIC );
bool setTimer( timer_t timerId,
const time_t interval_sec,
const long interval_nsec = 0,
const time_t initExpr_sec = 0,
const long initExpr_nsec = 0 );
void stopTimer( timer_t timerId );
bool stopTimer( timer_t timerId );
private:
std::map< timer_t, TimerUser* > m_timerUsers;
typedef std::map<timer_t, TimerUser*> TimerUserMap;
TimerUserMap m_timerUsers;
}; // class Timer

@ -1,5 +1,6 @@
#include "Timer.hpp"
#include "Logger.hpp"
#include "Common.hpp"
#include <signal.h> // sigset_t
@ -10,11 +11,12 @@ void notifyFunction(union sigval sigVal)
{
TRACE_STATIC;
((TimerUser *)(sigVal.sival_ptr))->timerExpired();
reinterpret_cast<TimerUser*>(sigVal.sival_ptr)->timerExpired();
}
Timer::Timer() : m_timerUsers()
Timer::Timer()
: m_timerUsers()
{
TRACE;
}
@ -23,68 +25,80 @@ Timer::~Timer()
{
TRACE;
struct itimerspec its;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 0;
for (TimerUserMap::iterator it = m_timerUsers.begin(); it != m_timerUsers.end(); )
stopTimer((it++)->first);
std::map< timer_t, TimerUser* >::iterator it;
for ( it = m_timerUsers.begin(); it != m_timerUsers.end(); it++ ) {
timer_settime( it->first , 0, &its, 0 );
it->second->timerDestroyed();
}
m_timerUsers.clear();
}
timer_t Timer::createTimer( TimerUser *timerUser,
const time_t interval_sec,
const long interval_nsec,
const time_t initExpr_sec,
const long initExpr_nsec )
clockid_t clockId )
{
TRACE;
// create timer
struct sigevent sigev;
timer_t timerId;
sigevent sigev;
timer_t timerId(0);
sigev.sigev_notify = SIGEV_THREAD;
sigev.sigev_value.sival_ptr = timerUser;
sigev.sigev_notify_function = notifyFunction;
sigev.sigev_notify_attributes = 0;
/// @bug passing address of local variable
timer_create( CLOCK_REALTIME, &sigev, &timerId );
if (timer_create(clockId, &sigev, &timerId) == -1) {
LOG_BEGIN(Logger::ERR)
LOG_PROP("Error message", strerror(errno))
LOG_END("Could create timer.");
return 0;
}
if (m_timerUsers.find(timerId) != m_timerUsers.end() ) {
LOG_BEGIN(Logger::ERR)
LOG_SPROP(timerId)
LOG_END("TimerId already in map.");
return 0;
}
m_timerUsers.insert(std::make_pair(timerId, timerUser));
return timerId;
}
// arm it
struct itimerspec its;
bool Timer::setTimer( timer_t timerId,
const time_t interval_sec,
const long interval_nsec,
const time_t initExpr_sec,
const long initExpr_nsec )
{
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;
timer_settime( timerId, 0, &its, 0 );
m_timerUsers.insert( std::make_pair( timerId, timerUser ) );
return timerId;
if (timer_settime( timerId, 0, &its, NULL ) == -1) {
LOG_BEGIN(Logger::ERR)
LOG_PROP("Error message", strerror(errno))
LOG_END("Could set timer.");
return false;
}
return true;
}
void Timer::stopTimer( timer_t timerId )
bool Timer::stopTimer( timer_t timerId )
{
TRACE;
/// @bug why is this needed?
timer_t tmp = timerId;
// disarm timer
struct itimerspec its;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 0;
if ( timer_settime( tmp, 0, &its, 0 ) == -1 ) {
LOG( Logger::ERR, strerror( errno ) );
if (m_timerUsers.find(timerId) == m_timerUsers.end() ) {
LOG_BEGIN(Logger::ERR)
LOG_SPROP(timerId)
LOG_END("TimerId is not in the map.");
return false;
}
m_timerUsers[ tmp ]->timerDestroyed();
m_timerUsers.erase( tmp );
setTimer(timerId, 0);
m_timerUsers[timerId]->timerDestroyed();
m_timerUsers.erase(timerId);
return true;
}

@ -18,9 +18,28 @@ private:
{
public:
DummyTimerUser() : m_counter( 0 ) { TRACE; }
void timerExpired() { /*TRACE;*/ m_counter += 100; }
void timerDestroyed() { TRACE; m_counter++; };
DummyTimerUser()
: m_counter(0)
{
TRACE;
}
~DummyTimerUser()
{
TRACE;
}
void timerExpired()
{
TRACE;
m_counter++;
}
void timerDestroyed()
{
TRACE;
m_counter += 100;
}
int m_counter;
@ -28,81 +47,59 @@ private:
public:
void testBasicTimerThread( void )
void testBasicTimer( void )
{
TEST_HEADER;
DummyTimerUser timerUser;
Timer timer;
timer.createTimer( &timerUser, 2 );
timer_t timerId = timer.createTimer( &timerUser );
timer.setTimer(timerId, 2);
sleep( 4 );
// no destroy
TS_ASSERT_EQUALS( timerUser.m_counter, 100 );
// one expiration, no destroy
TS_ASSERT_EQUALS( timerUser.m_counter, 1 );
}
void testStopTimerThread( void )
void testStopTimer( void )
{
TEST_HEADER;
DummyTimerUser timerUser;
Timer timer;
timer_t timerId = timer.createTimer( &timerUser, 10 );
timer_t timerId = timer.createTimer( &timerUser );
timer.setTimer(timerId, 10);
sleep( 2 );
timer.stopTimer( timerId );
TS_ASSERT_EQUALS( timerUser.m_counter, 1 );
// no expiration, just destroy
TS_ASSERT_EQUALS( timerUser.m_counter, 100 );
}
void testPeriodicTimerThread( void )
void testPeriodicTimer( void )
{
TEST_HEADER;
DummyTimerUser timerUser;
Timer timer;
timer_t timerId = timer.createTimer( &timerUser,
1, 0,
1, 0 );
timer_t timerId = timer.createTimer( &timerUser );
// after 1 sec, expire periodically at each sec
timer.setTimer(timerId, 1, 0, 1, 0);
sleep(4);
timer.stopTimer( timerId );
sleep(4); // did it really stopped?
TS_ASSERT_EQUALS( timerUser.m_counter, 400 + 1 );
// 1 destroy(stop) + 3 expiration (+- 1)
TS_ASSERT_DELTA( timerUser.m_counter, 103, 1 );
}
void testTimerThreadHighFreq( void )
{
TEST_HEADER;
int nano = 1000000000; // 10^9
int freq = 200;
DummyTimerUser timerUser;
Timer timer;
timer_t timerId = timer.createTimer( &timerUser,
1, 0,
0, nano / freq );
int circle = 2;
sleep( 1 + circle );
timer.stopTimer( timerId );
TS_ASSERT_DELTA ( timerUser.m_counter, 100 * freq * circle + 1,
(100 * freq * circle + 1 ) * 0.9);
sleep(1);
}
void testOneUserManyTimers( void )
{
TEST_HEADER;
@ -110,31 +107,18 @@ private:
DummyTimerUser timerUser;
Timer timer;
timer_t timerId = timer.createTimer( &timerUser,
1, 0,
1, 0 );
timer_t timerId = timer.createTimer( &timerUser );
timer.setTimer(timerId, 1);
timer_t timerId2 = timer.createTimer( &timerUser,
1, 0,
2, 0 );
timer_t timerId2 = timer.createTimer( &timerUser );
timer.setTimer(timerId2, 2);
timer_t timerId3 = timer.createTimer( &timerUser,
1, 0,
3, 0 );
timer_t timerId3 = timer.createTimer( &timerUser );
timer.setTimer(timerId3, 3);
sleep(4);
timer.stopTimer( timerId );
TS_ASSERT_EQUALS( timerUser.m_counter, 400 + 200 + 200 + 1 );
sleep(4);
TS_ASSERT_EQUALS( timerUser.m_counter, 400 + 200 + 200 + 200 + 100 + 1 );
timer.stopTimer( timerId2 );
timer.stopTimer( timerId3 );
sleep(1);
TS_ASSERT_EQUALS( timerUser.m_counter, 400 + 200 + 200 + 200 + 100 + 3 );
TS_ASSERT_EQUALS( timerUser.m_counter, 100 + 1 + 1 + 1 );
}
void testMenyUserManyTimers( void )
@ -147,38 +131,22 @@ private:
Timer timer;
timer_t timerId = timer.createTimer( &timerUser,
1, 0,
1, 0 );
timer_t timerId2 = timer.createTimer( &timerUser,
1, 0,
2, 0 );
timer_t timerId3 = timer.createTimer( &timerUser,
1, 0,
3, 0 );
timer_t timerId4 = timer.createTimer( &timerUser2,
1, 0,
1, 0 );
timer_t timerId5 = timer.createTimer( &timerUser2,
1, 0,
2, 0 );
timer_t timerId = timer.createTimer( &timerUser );
timer.setTimer(timerId, 1);
timer_t timerId2 = timer.createTimer( &timerUser );
timer.setTimer(timerId2, 2);
timer_t timerId3 = timer.createTimer( &timerUser );
timer.setTimer(timerId3, 3);
timer_t timerId4 = timer.createTimer( &timerUser2 );
timer.setTimer(timerId4, 1);
timer_t timerId5 = timer.createTimer( &timerUser2 );
timer.setTimer(timerId5, 2);
sleep(4);
TS_ASSERT_EQUALS( timerUser.m_counter, 400 + 200 + 200 );
TS_ASSERT_EQUALS( timerUser2.m_counter, 400 + 200 );
timer.stopTimer( timerId );
timer.stopTimer( timerId2 );
timer.stopTimer( timerId3 );
timer.stopTimer( timerId4 );
timer.stopTimer( timerId5 );
sleep(1);
TS_ASSERT_EQUALS( timerUser.m_counter, 1 + 1 + 1 );
TS_ASSERT_EQUALS( timerUser2.m_counter, 1 + 1 );
TS_ASSERT_EQUALS( timerUser3.m_counter, 0 );
}
void test2Timer( void )
@ -186,44 +154,35 @@ private:
TEST_HEADER;
DummyTimerUser timerUser;
DummyTimerUser timerUser2;
DummyTimerUser itmerUser3;
Timer timer;
Timer timer2;
timer_t timerId = timer.createTimer( &timerUser,
1, 0,
1, 0 );
timer_t timerId2 = timer.createTimer( &timerUser,
1, 0,
2, 0 );
timer_t timerId3 = timer2.createTimer( &timerUser,
1, 0,
3, 0 );
timer_t timerId4 = timer.createTimer( &timerUser2,
1, 0,
1, 0 );
timer_t timerId = timer.createTimer( &timerUser );
timer.setTimer(timerId, 1);
timer_t timerId2 = timer.createTimer( &timerUser );
timer.setTimer(timerId2, 2);
timer_t timerId3 = timer.createTimer( &timerUser );
timer.setTimer(timerId3, 3);
timer_t timerId5 = timer2.createTimer( &timerUser2,
1, 0,
2, 0 );
timer_t timerId4 = timer.createTimer( &timerUser );
timer2.setTimer(timerId4, 1);
timer_t timerId5 = timer.createTimer( &timerUser );
timer2.setTimer(timerId5, 2);
sleep(4);
TS_ASSERT_EQUALS( timerUser.m_counter, 400 + 200 + 200 );
TS_ASSERT_EQUALS( timerUser2.m_counter, 400 + 200 );
TS_ASSERT_EQUALS( timerUser.m_counter, (1 + 1 + 1) + (1 + 1) );
}
timer.stopTimer( timerId );
timer.stopTimer( timerId2 );
timer2.stopTimer( timerId3 );
timer.stopTimer( timerId4 );
timer2.stopTimer( timerId5 );
void testStopTimerWhichIsNotInTheMap()
{
TEST_HEADER;
Timer timer;
sleep(1);
timer_t timerId = (void*)1234;
TS_ASSERT_EQUALS(timer.stopTimer( timerId ), false);
}
};

Loading…
Cancel
Save