mirror of
https://github.com/pocoproject/poco.git
synced 2025-03-04 19:13:30 +01:00
Merge pull request #3999 from vojinilic/fixDeadLockDestructor
Fix hang in destructor
This commit is contained in:
commit
dd21b48d05
@ -89,6 +89,16 @@ public:
|
|||||||
/// assigned to a Notification::Ptr, to avoid potential
|
/// assigned to a Notification::Ptr, to avoid potential
|
||||||
/// memory management issues.
|
/// memory management issues.
|
||||||
|
|
||||||
|
Notification* dequeueNextNotification();
|
||||||
|
/// Dequeues the next notification regardless of timestamp.
|
||||||
|
/// Returns 0 (null) if no notification is available.
|
||||||
|
/// The caller gains ownership of the notification and
|
||||||
|
/// is expected to release it when done with it.
|
||||||
|
///
|
||||||
|
/// It is highly recommended that the result is immediately
|
||||||
|
/// assigned to a Notification::Ptr, to avoid potential
|
||||||
|
/// memory management issues.
|
||||||
|
|
||||||
Notification* waitDequeueNotification();
|
Notification* waitDequeueNotification();
|
||||||
/// Dequeues the next pending notification.
|
/// Dequeues the next pending notification.
|
||||||
/// If no notification is available, waits for a notification
|
/// If no notification is available, waits for a notification
|
||||||
|
@ -82,6 +82,20 @@ Notification* TimedNotificationQueue::dequeueNotification()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Notification* TimedNotificationQueue::dequeueNextNotification()
|
||||||
|
{
|
||||||
|
FastMutex::ScopedLock lock(_mutex);
|
||||||
|
|
||||||
|
NfQueue::iterator it = _nfQueue.begin();
|
||||||
|
if (it != _nfQueue.end())
|
||||||
|
{
|
||||||
|
Notification::Ptr pNf = it->second;
|
||||||
|
_nfQueue.erase(it);
|
||||||
|
return pNf.duplicate();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Notification* TimedNotificationQueue::waitDequeueNotification()
|
Notification* TimedNotificationQueue::waitDequeueNotification()
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -139,6 +139,25 @@ void TimedNotificationQueueTest::testDequeue()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TimedNotificationQueueTest::testDequeueNext()
|
||||||
|
{
|
||||||
|
TimedNotificationQueue queue;
|
||||||
|
assertTrue (queue.empty());
|
||||||
|
assertTrue (queue.size() == 0);
|
||||||
|
Notification* pNf = queue.dequeueNextNotification();
|
||||||
|
assertNullPtr(pNf);
|
||||||
|
Timestamp time;
|
||||||
|
time += 100000;
|
||||||
|
queue.enqueueNotification(new Notification, time);
|
||||||
|
assertTrue (!queue.empty());
|
||||||
|
assertTrue (queue.size() == 1);
|
||||||
|
pNf = queue.dequeueNextNotification();
|
||||||
|
assertNotNullPtr(pNf);
|
||||||
|
assertTrue (queue.empty());
|
||||||
|
assertTrue (queue.size() == 0);
|
||||||
|
pNf->release();
|
||||||
|
}
|
||||||
|
|
||||||
void TimedNotificationQueueTest::testWaitDequeue()
|
void TimedNotificationQueueTest::testWaitDequeue()
|
||||||
{
|
{
|
||||||
TimedNotificationQueue queue;
|
TimedNotificationQueue queue;
|
||||||
@ -264,6 +283,7 @@ CppUnit::Test* TimedNotificationQueueTest::suite()
|
|||||||
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TimedNotificationQueueTest");
|
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("TimedNotificationQueueTest");
|
||||||
|
|
||||||
CppUnit_addTest(pSuite, TimedNotificationQueueTest, testDequeue);
|
CppUnit_addTest(pSuite, TimedNotificationQueueTest, testDequeue);
|
||||||
|
CppUnit_addTest(pSuite, TimedNotificationQueueTest, testDequeueNext);
|
||||||
CppUnit_addTest(pSuite, TimedNotificationQueueTest, testWaitDequeue);
|
CppUnit_addTest(pSuite, TimedNotificationQueueTest, testWaitDequeue);
|
||||||
CppUnit_addTest(pSuite, TimedNotificationQueueTest, testWaitDequeueTimeout);
|
CppUnit_addTest(pSuite, TimedNotificationQueueTest, testWaitDequeueTimeout);
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ public:
|
|||||||
~TimedNotificationQueueTest();
|
~TimedNotificationQueueTest();
|
||||||
|
|
||||||
void testDequeue();
|
void testDequeue();
|
||||||
|
void testDequeueNext();
|
||||||
void testWaitDequeue();
|
void testWaitDequeue();
|
||||||
void testWaitDequeueTimeout();
|
void testWaitDequeueTimeout();
|
||||||
|
|
||||||
|
@ -84,9 +84,15 @@ public:
|
|||||||
bool execute()
|
bool execute()
|
||||||
{
|
{
|
||||||
// Check if there's a StopNotification pending.
|
// Check if there's a StopNotification pending.
|
||||||
Poco::AutoPtr<TimerNotification> pNf = static_cast<TimerNotification*>(queue().dequeueNotification());
|
int numberOfPendingTasks = queue().size();
|
||||||
while (pNf)
|
while (numberOfPendingTasks > 0)
|
||||||
{
|
{
|
||||||
|
Poco::AutoPtr<TimerNotification> pNf = static_cast<TimerNotification*>(queue().dequeueNextNotification());
|
||||||
|
numberOfPendingTasks--;
|
||||||
|
if (!pNf)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (pNf.cast<StopNotification>())
|
if (pNf.cast<StopNotification>())
|
||||||
{
|
{
|
||||||
queue().clear();
|
queue().clear();
|
||||||
@ -98,10 +104,8 @@ public:
|
|||||||
{
|
{
|
||||||
pCnf->_finished.set();
|
pCnf->_finished.set();
|
||||||
}
|
}
|
||||||
pNf = static_cast<TimerNotification*>(queue().dequeueNotification());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
queue().clear();
|
|
||||||
_finished.set();
|
_finished.set();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -231,11 +231,16 @@ void TimerTest::testCancelAllStop()
|
|||||||
|
|
||||||
TimerTask::Ptr pTask = new TimerTaskAdapter<TimerTest>(*this, &TimerTest::onTimer);
|
TimerTask::Ptr pTask = new TimerTaskAdapter<TimerTest>(*this, &TimerTest::onTimer);
|
||||||
|
|
||||||
timer.scheduleAtFixedRate(pTask, 5000, 5000);
|
// We are scheduling a timer event in 100ms
|
||||||
|
Timestamp time;
|
||||||
Poco::Thread::sleep(100);
|
time += 100000;
|
||||||
|
timer.schedule(pTask, time);
|
||||||
|
|
||||||
timer.cancel(false);
|
timer.cancel(false);
|
||||||
|
// Timer should fire in 100ms and onTimer has 100ms sleep in it.
|
||||||
|
// So we are waiting 2 times that plus a small buffer that to make sure that event was never executed.
|
||||||
|
bool timerExecuted = _event.tryWait(200 + 50);
|
||||||
|
assertFalse (timerExecuted);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue (true); // don't hang
|
assertTrue (true); // don't hang
|
||||||
@ -249,11 +254,16 @@ void TimerTest::testCancelAllWaitStop()
|
|||||||
|
|
||||||
TimerTask::Ptr pTask = new TimerTaskAdapter<TimerTest>(*this, &TimerTest::onTimer);
|
TimerTask::Ptr pTask = new TimerTaskAdapter<TimerTest>(*this, &TimerTest::onTimer);
|
||||||
|
|
||||||
timer.scheduleAtFixedRate(pTask, 5000, 5000);
|
// We are scheduling a timer event in 100ms
|
||||||
|
Timestamp time;
|
||||||
Poco::Thread::sleep(100);
|
time += 100000;
|
||||||
|
timer.schedule(pTask, time);
|
||||||
|
|
||||||
timer.cancel(true);
|
timer.cancel(true);
|
||||||
|
// Timer should fire in 100ms and onTimer has 100ms sleep in it.
|
||||||
|
// So we are waiting 2 times that plus a small buffer that to make sure that event was never executed.
|
||||||
|
bool timerExecuted = _event.tryWait(200 + 50);
|
||||||
|
assertFalse (timerExecuted);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertTrue (true); // don't hang
|
assertTrue (true); // don't hang
|
||||||
|
Loading…
x
Reference in New Issue
Block a user