diff --git a/include/Timer.hpp b/include/Timer.hpp index b67f80d..8581e5f 100644 --- a/include/Timer.hpp +++ b/include/Timer.hpp @@ -2,7 +2,6 @@ #define TIMER_HPP -#include // sigset_t #include // timer_t #include @@ -29,18 +28,22 @@ public: virtual ~Timer(); timer_t createTimer( TimerUser *m_timerUser, - const time_t interval_sec, - const long interval_nsec = 0, - const time_t initExpr_sec = 0, - const long initExpr_nsec = 0 ); + 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 TimerUserMap; + + TimerUserMap m_timerUsers; }; // class Timer diff --git a/src/Timer.cpp b/src/Timer.cpp index 9b750a1..b2b86dc 100644 --- a/src/Timer.cpp +++ b/src/Timer.cpp @@ -1,5 +1,6 @@ #include "Timer.hpp" +#include "Logger.hpp" #include "Common.hpp" #include // sigset_t @@ -10,11 +11,12 @@ void notifyFunction(union sigval sigVal) { TRACE_STATIC; - ((TimerUser *)(sigVal.sival_ptr))->timerExpired(); + reinterpret_cast(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; } diff --git a/test/test_Timer.hpp b/test/test_Timer.hpp index 6b6f1ff..9a75e1c 100644 --- a/test/test_Timer.hpp +++ b/test/test_Timer.hpp @@ -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,83 +131,58 @@ 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 ) + void test2Timer( void ) { 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 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, - 1, 0, - 1, 0 ); - - 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); } };