mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-20 05:49:04 +02:00
fixed GH #2058: Synchronization issue in Poco::Util::Timer at destruction
This commit is contained in:
@@ -32,18 +32,18 @@ public:
|
|||||||
_queue(queue)
|
_queue(queue)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~TimerNotification()
|
~TimerNotification()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool execute() = 0;
|
virtual bool execute() = 0;
|
||||||
|
|
||||||
Poco::TimedNotificationQueue& queue()
|
Poco::TimedNotificationQueue& queue()
|
||||||
{
|
{
|
||||||
return _queue;
|
return _queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Poco::TimedNotificationQueue& _queue;
|
Poco::TimedNotificationQueue& _queue;
|
||||||
};
|
};
|
||||||
@@ -56,11 +56,11 @@ public:
|
|||||||
TimerNotification(queue)
|
TimerNotification(queue)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~StopNotification()
|
~StopNotification()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool execute()
|
bool execute()
|
||||||
{
|
{
|
||||||
queue().clear();
|
queue().clear();
|
||||||
@@ -76,23 +76,36 @@ public:
|
|||||||
TimerNotification(queue)
|
TimerNotification(queue)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~CancelNotification()
|
~CancelNotification()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool execute()
|
bool execute()
|
||||||
{
|
{
|
||||||
|
// Check if there's a StopNotification pending.
|
||||||
|
Poco::AutoPtr<TimerNotification> pNf = static_cast<TimerNotification*>(queue().dequeueNotification());
|
||||||
|
while (pNf)
|
||||||
|
{
|
||||||
|
if (pNf.cast<StopNotification>())
|
||||||
|
{
|
||||||
|
queue().clear();
|
||||||
|
_finished.set();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pNf = static_cast<TimerNotification*>(queue().dequeueNotification());
|
||||||
|
}
|
||||||
|
|
||||||
queue().clear();
|
queue().clear();
|
||||||
_finished.set();
|
_finished.set();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait()
|
void wait()
|
||||||
{
|
{
|
||||||
_finished.wait();
|
_finished.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Poco::Event _finished;
|
Poco::Event _finished;
|
||||||
};
|
};
|
||||||
@@ -106,16 +119,16 @@ public:
|
|||||||
_pTask(pTask)
|
_pTask(pTask)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~TaskNotification()
|
~TaskNotification()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TimerTask::Ptr task()
|
TimerTask::Ptr task()
|
||||||
{
|
{
|
||||||
return _pTask;
|
return _pTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool execute()
|
bool execute()
|
||||||
{
|
{
|
||||||
if (!_pTask->isCancelled())
|
if (!_pTask->isCancelled())
|
||||||
@@ -140,7 +153,7 @@ public:
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TimerTask::Ptr _pTask;
|
TimerTask::Ptr _pTask;
|
||||||
};
|
};
|
||||||
@@ -154,13 +167,13 @@ public:
|
|||||||
_interval(interval)
|
_interval(interval)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~PeriodicTaskNotification()
|
~PeriodicTaskNotification()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool execute()
|
bool execute()
|
||||||
{
|
{
|
||||||
TaskNotification::execute();
|
TaskNotification::execute();
|
||||||
|
|
||||||
if (!task()->isCancelled())
|
if (!task()->isCancelled())
|
||||||
@@ -172,9 +185,9 @@ public:
|
|||||||
queue().enqueueNotification(this, nextExecution);
|
queue().enqueueNotification(this, nextExecution);
|
||||||
duplicate();
|
duplicate();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
long _interval;
|
long _interval;
|
||||||
};
|
};
|
||||||
@@ -189,13 +202,13 @@ public:
|
|||||||
_nextExecution(clock)
|
_nextExecution(clock)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~FixedRateTaskNotification()
|
~FixedRateTaskNotification()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool execute()
|
bool execute()
|
||||||
{
|
{
|
||||||
TaskNotification::execute();
|
TaskNotification::execute();
|
||||||
|
|
||||||
if (!task()->isCancelled())
|
if (!task()->isCancelled())
|
||||||
@@ -206,9 +219,9 @@ public:
|
|||||||
queue().enqueueNotification(this, _nextExecution);
|
queue().enqueueNotification(this, _nextExecution);
|
||||||
duplicate();
|
duplicate();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
long _interval;
|
long _interval;
|
||||||
Poco::Clock _nextExecution;
|
Poco::Clock _nextExecution;
|
||||||
@@ -241,7 +254,7 @@ Timer::~Timer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Timer::cancel(bool wait)
|
void Timer::cancel(bool wait)
|
||||||
{
|
{
|
||||||
Poco::AutoPtr<CancelNotification> pNf = new CancelNotification(_queue);
|
Poco::AutoPtr<CancelNotification> pNf = new CancelNotification(_queue);
|
||||||
@@ -266,7 +279,7 @@ void Timer::schedule(TimerTask::Ptr pTask, Poco::Clock clock)
|
|||||||
_queue.enqueueNotification(new TaskNotification(_queue, pTask), clock);
|
_queue.enqueueNotification(new TaskNotification(_queue, pTask), clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Timer::schedule(TimerTask::Ptr pTask, long delay, long interval)
|
void Timer::schedule(TimerTask::Ptr pTask, long delay, long interval)
|
||||||
{
|
{
|
||||||
Poco::Clock clock;
|
Poco::Clock clock;
|
||||||
@@ -288,7 +301,7 @@ void Timer::schedule(TimerTask::Ptr pTask, Poco::Clock clock, long interval)
|
|||||||
_queue.enqueueNotification(new PeriodicTaskNotification(_queue, pTask, interval), clock);
|
_queue.enqueueNotification(new PeriodicTaskNotification(_queue, pTask, interval), clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Timer::scheduleAtFixedRate(TimerTask::Ptr pTask, long delay, long interval)
|
void Timer::scheduleAtFixedRate(TimerTask::Ptr pTask, long delay, long interval)
|
||||||
{
|
{
|
||||||
Poco::Clock clock;
|
Poco::Clock clock;
|
||||||
|
@@ -197,18 +197,18 @@ void TimerTest::testScheduleAtFixedRate()
|
|||||||
void TimerTest::testCancel()
|
void TimerTest::testCancel()
|
||||||
{
|
{
|
||||||
Timer timer;
|
Timer timer;
|
||||||
|
|
||||||
Timestamp time;
|
Timestamp time;
|
||||||
|
|
||||||
TimerTask::Ptr pTask = new TimerTaskAdapter<TimerTest>(*this, &TimerTest::onTimer);
|
TimerTask::Ptr pTask = new TimerTaskAdapter<TimerTest>(*this, &TimerTest::onTimer);
|
||||||
|
|
||||||
assert (pTask->lastExecution() == 0);
|
assert (pTask->lastExecution() == 0);
|
||||||
|
|
||||||
timer.scheduleAtFixedRate(pTask, 5000, 5000);
|
timer.scheduleAtFixedRate(pTask, 5000, 5000);
|
||||||
|
|
||||||
pTask->cancel();
|
pTask->cancel();
|
||||||
assert (pTask->isCancelled());
|
assert (pTask->isCancelled());
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
timer.scheduleAtFixedRate(pTask, 5000, 5000);
|
timer.scheduleAtFixedRate(pTask, 5000, 5000);
|
||||||
@@ -224,6 +224,42 @@ void TimerTest::testCancel()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TimerTest::testCancelAllStop()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Timer timer;
|
||||||
|
|
||||||
|
TimerTask::Ptr pTask = new TimerTaskAdapter<TimerTest>(*this, &TimerTest::onTimer);
|
||||||
|
|
||||||
|
timer.scheduleAtFixedRate(pTask, 5000, 5000);
|
||||||
|
|
||||||
|
Poco::Thread::sleep(100);
|
||||||
|
|
||||||
|
timer.cancel(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (true); // don't hang
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TimerTest::testCancelAllWaitStop()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Timer timer;
|
||||||
|
|
||||||
|
TimerTask::Ptr pTask = new TimerTaskAdapter<TimerTest>(*this, &TimerTest::onTimer);
|
||||||
|
|
||||||
|
timer.scheduleAtFixedRate(pTask, 5000, 5000);
|
||||||
|
|
||||||
|
Poco::Thread::sleep(100);
|
||||||
|
|
||||||
|
timer.cancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (true); // don't hang
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TimerTest::setUp()
|
void TimerTest::setUp()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -252,6 +288,8 @@ CppUnit::Test* TimerTest::suite()
|
|||||||
CppUnit_addTest(pSuite, TimerTest, testScheduleIntervalClock);
|
CppUnit_addTest(pSuite, TimerTest, testScheduleIntervalClock);
|
||||||
CppUnit_addTest(pSuite, TimerTest, testScheduleAtFixedRate);
|
CppUnit_addTest(pSuite, TimerTest, testScheduleAtFixedRate);
|
||||||
CppUnit_addTest(pSuite, TimerTest, testCancel);
|
CppUnit_addTest(pSuite, TimerTest, testCancel);
|
||||||
|
CppUnit_addTest(pSuite, TimerTest, testCancelAllStop);
|
||||||
|
CppUnit_addTest(pSuite, TimerTest, testCancelAllWaitStop);
|
||||||
|
|
||||||
return pSuite;
|
return pSuite;
|
||||||
}
|
}
|
||||||
|
@@ -33,6 +33,8 @@ public:
|
|||||||
void testScheduleIntervalTimestamp();
|
void testScheduleIntervalTimestamp();
|
||||||
void testScheduleIntervalClock();
|
void testScheduleIntervalClock();
|
||||||
void testCancel();
|
void testCancel();
|
||||||
|
void testCancelAllStop();
|
||||||
|
void testCancelAllWaitStop();
|
||||||
|
|
||||||
void setUp();
|
void setUp();
|
||||||
void tearDown();
|
void tearDown();
|
||||||
|
Reference in New Issue
Block a user