TimerThead uses nanosec precision

master
Denes Matetelki 14 years ago
parent 83f61e602c
commit 38d7e7c692

@ -7,7 +7,7 @@
#include "ConditionVariable.hpp" #include "ConditionVariable.hpp"
#include <map> #include <map>
#include <ctime> // time_t #include <time.h> // timespec
class TimerUser class TimerUser
{ {
@ -29,7 +29,7 @@ class TimerThread : public Thread
private: private:
typedef struct { typedef struct {
time_t periodTime; timespec periodTime;
TimerUser* user; TimerUser* user;
} UserEntry; } UserEntry;
@ -40,9 +40,13 @@ public:
virtual ~TimerThread(); virtual ~TimerThread();
void addTimerUser(TimerUser* user, void addTimerUser( TimerUser* user,
const time_t expiration, const time_t expiration,
const time_t periodTime = 0 ); const time_t periodTime = 0 );
void addTimerUser( TimerUser* user,
const timespec expiration,
const timespec periodTime = timespec_ctor() );
bool removeTimerUser ( void* timerUser ); bool removeTimerUser ( void* timerUser );
@ -54,10 +58,26 @@ private:
void* run( void ); void* run( void );
// facory function
inline static timespec timespec_ctor() {
timespec tmp = { 0, 0 };
return tmp;
};
// compare class for the multimap
class timespec_cmp {
public :
bool operator()(const timespec& a, const timespec& b) const {
if ( a.tv_sec < b.tv_sec ) return true;
if ( a.tv_sec > b.tv_sec ) return false;
return a.tv_nsec < b.tv_nsec;
}
};
Mutex m_mutex; Mutex m_mutex;
ConditionVariable m_condVar; ConditionVariable m_condVar;
std::multimap<time_t, UserEntry> m_users; std::multimap< timespec, UserEntry, timespec_cmp> m_users;
}; // class TimerThread }; // class TimerThread

@ -31,24 +31,39 @@ void TimerThread::addTimerUser(TimerUser* user,
TRACE; TRACE;
ScopedLock sl( m_mutex ); ScopedLock sl( m_mutex );
if ( not m_isRunning ) return; if ( not m_isRunning ) return;
UserEntry userEntry = { periodTime, user }; timespec expirationTS = { expiration, 0 };
m_users.insert( std::pair<time_t, UserEntry>( expiration, userEntry ) ); timespec periodTimeTS = { periodTime, 0 };
UserEntry userEntry = { periodTimeTS, user };
m_users.insert( std::pair<timespec, UserEntry>( expirationTS, userEntry ) );
m_condVar.signal(); m_condVar.signal();
} }
void TimerThread::addTimerUser( TimerUser* user,
const timespec expiration,
const timespec periodTime )
{
TRACE;
ScopedLock sl( m_mutex );
if ( not m_isRunning ) return;
UserEntry userEntry = { periodTime, user };
m_users.insert( std::pair<timespec, UserEntry>( expiration, userEntry ) );
m_condVar.signal();
}
bool TimerThread::removeTimerUser ( void* timerUser ) bool TimerThread::removeTimerUser ( void* timerUser )
{ {
TRACE; TRACE;
ScopedLock sl( m_mutex ); ScopedLock sl( m_mutex );
if ( not m_isRunning ) return false; if ( not m_isRunning ) return false;
std::multimap<time_t, UserEntry>::iterator it, tmp; std::multimap<timespec, UserEntry>::iterator it, tmp;
bool found(false); bool found(false);
for ( it = m_users.begin(); it != m_users.end(); ) { for ( it = m_users.begin(); it != m_users.end(); ) {
tmp = it++; tmp = it++;
/// @todo solveth e abstract pointer problem /// @todo solve the abstract pointer problem
if ( (void*)(it->second.user) == (void*)timerUser ) { if ( (void*)(it->second.user) == (void*)timerUser ) {
m_users.erase(tmp); m_users.erase(tmp);
m_condVar.signal(); m_condVar.signal();
@ -71,12 +86,12 @@ void TimerThread::stop()
void* TimerThread::run( void ) void* TimerThread::run( void )
{ {
TRACE; TRACE;
time_t nextExpiration; timespec nextExpiration;
std::multimap<time_t, UserEntry> tmp; std::multimap<timespec, UserEntry, timespec_cmp> tmp;
std::multimap<time_t, UserEntry>::iterator it; std::multimap<timespec, UserEntry>::iterator it;
std::pair<std::multimap<time_t, UserEntry>::iterator, std::pair<std::multimap<timespec, UserEntry>::iterator,
std::multimap<time_t, UserEntry>::iterator> ret; std::multimap<timespec, UserEntry>::iterator> ret;
while( m_isRunning ) { while( m_isRunning ) {
@ -91,7 +106,8 @@ void* TimerThread::run( void )
m_mutex.lock(); m_mutex.lock();
// timer deleted / added, get nextExpiration again // timer deleted / added, get nextExpiration again
if ( m_condVar.wait( nextExpiration ) != ETIMEDOUT ) { if ( m_condVar.wait( nextExpiration.tv_sec,
nextExpiration.tv_nsec ) != ETIMEDOUT ) {
continue; continue;
} }
m_mutex.unlock(); m_mutex.unlock();
@ -104,7 +120,8 @@ void* TimerThread::run( void )
tmp.clear(); tmp.clear();
for ( it = ret.first; it != ret.second; it++ ) { for ( it = ret.first; it != ret.second; it++ ) {
it->second.user->timerExpired(); it->second.user->timerExpired();
if ( it->second.periodTime ) tmp.insert(std::pair<time_t, UserEntry>( if ( it->second.periodTime.tv_sec != 0 or it->second.periodTime.tv_nsec != 0)
tmp.insert(std::pair<timespec, UserEntry>(
it->second.periodTime, it->second ) ); it->second.periodTime, it->second ) );
} }
m_users.erase( nextExpiration ); m_users.erase( nextExpiration );

Loading…
Cancel
Save