added Clock class which provides a monotonic clock on most platforms and is now used by Poco::Timer, Poco::Stopwatch, Poco::TimedNotificationQueue and Poco::UtilTimer to avoid issues when the system time is changed

This commit is contained in:
Guenter Obiltschnig
2013-12-12 18:33:29 +01:00
parent 5edb90c48e
commit ac2b26fcb9
47 changed files with 884 additions and 48 deletions

View File

@@ -1,7 +1,7 @@
//
// TimedNotificationQueue.cpp
//
// $Id: //poco/1.4/Foundation/src/TimedNotificationQueue.cpp#1 $
// $Id: //poco/1.4/Foundation/src/TimedNotificationQueue.cpp#2 $
//
// Library: Foundation
// Package: Notifications
@@ -57,8 +57,23 @@ void TimedNotificationQueue::enqueueNotification(Notification::Ptr pNotification
{
poco_check_ptr (pNotification);
Timestamp tsNow;
Clock clock;
Timestamp::TimeDiff diff = timestamp - tsNow;
clock += diff;
FastMutex::ScopedLock lock(_mutex);
_nfQueue.insert(NfQueue::value_type(timestamp, pNotification));
_nfQueue.insert(NfQueue::value_type(clock, pNotification));
_nfAvailable.set();
}
void TimedNotificationQueue::enqueueNotification(Notification::Ptr pNotification, Clock clock)
{
poco_check_ptr (pNotification);
FastMutex::ScopedLock lock(_mutex);
_nfQueue.insert(NfQueue::value_type(clock, pNotification));
_nfAvailable.set();
}
@@ -70,7 +85,7 @@ Notification* TimedNotificationQueue::dequeueNotification()
NfQueue::iterator it = _nfQueue.begin();
if (it != _nfQueue.end())
{
Timestamp::TimeDiff sleep = -it->first.elapsed();
Clock::ClockDiff sleep = -it->first.elapsed();
if (sleep <= 0)
{
Notification::Ptr pNf = it->second;
@@ -91,7 +106,7 @@ Notification* TimedNotificationQueue::waitDequeueNotification()
if (it != _nfQueue.end())
{
_mutex.unlock();
Timestamp::TimeDiff sleep = -it->first.elapsed();
Clock::ClockDiff sleep = -it->first.elapsed();
if (sleep <= 0)
{
return dequeueOne(it).duplicate();
@@ -120,13 +135,13 @@ Notification* TimedNotificationQueue::waitDequeueNotification(long milliseconds)
if (it != _nfQueue.end())
{
_mutex.unlock();
Poco::Timestamp now;
Timestamp::TimeDiff sleep = it->first - now;
Clock now;
Clock::ClockDiff sleep = it->first - now;
if (sleep <= 0)
{
return dequeueOne(it).duplicate();
}
else if (sleep <= 1000*Timestamp::TimeDiff(milliseconds))
else if (sleep <= 1000*Clock::ClockDiff(milliseconds))
{
if (!wait(sleep))
{
@@ -145,7 +160,7 @@ Notification* TimedNotificationQueue::waitDequeueNotification(long milliseconds)
}
if (milliseconds > 0)
{
Poco::Timestamp now;
Clock now;
_nfAvailable.tryWait(milliseconds);
milliseconds -= static_cast<long>((now.elapsed() + 999)/1000);
}
@@ -155,13 +170,13 @@ Notification* TimedNotificationQueue::waitDequeueNotification(long milliseconds)
}
bool TimedNotificationQueue::wait(Timestamp::TimeDiff interval)
bool TimedNotificationQueue::wait(Clock::ClockDiff interval)
{
const Timestamp::TimeDiff MAX_SLEEP = 8*60*60*Timestamp::TimeDiff(1000000); // sleep at most 8 hours at a time
const Clock::ClockDiff MAX_SLEEP = 8*60*60*Clock::ClockDiff(1000000); // sleep at most 8 hours at a time
while (interval > 0)
{
Timestamp now;
Timestamp::TimeDiff sleep = interval <= MAX_SLEEP ? interval : MAX_SLEEP;
Clock now;
Clock::ClockDiff sleep = interval <= MAX_SLEEP ? interval : MAX_SLEEP;
if (_nfAvailable.tryWait(static_cast<long>((sleep + 999)/1000)))
return true;
interval -= now.elapsed();