util: Fix rescheduling and add test case.
Change-Id: Ic04a590a116083391b441338eed9a121e14852dd
diff --git a/src/util/scheduler.cpp b/src/util/scheduler.cpp
index 13a6c3a..c13e070 100644
--- a/src/util/scheduler.cpp
+++ b/src/util/scheduler.cpp
@@ -77,6 +77,7 @@
: m_ioService(ioService)
, m_scheduledEvent(m_events.end())
, m_deadlineTimer(ioService)
+ , m_isEventExecuting(false)
{
}
@@ -94,13 +95,16 @@
{
EventQueue::iterator i = m_events.insert(EventInfo(after, period, event));
i->m_eventId = make_shared<EventIdImpl>(boost::cref(i));
-
- if (m_scheduledEvent == m_events.end() ||
- *i < *m_scheduledEvent)
+
+ if (!m_isEventExecuting)
{
- m_deadlineTimer.expires_from_now(after);
- m_deadlineTimer.async_wait(bind(&Scheduler::onEvent, this, _1));
- m_scheduledEvent = i;
+ if (m_scheduledEvent == m_events.end() ||
+ *i < *m_scheduledEvent)
+ {
+ m_deadlineTimer.expires_from_now(after);
+ m_deadlineTimer.async_wait(bind(&Scheduler::onEvent, this, _1));
+ m_scheduledEvent = i;
+ }
}
return i->m_eventId;
@@ -122,16 +126,18 @@
m_events.erase(static_cast<EventQueue::iterator>(*eventId));
eventId->invalidate();
- if (!m_events.empty())
+ if (!m_isEventExecuting)
{
- m_deadlineTimer.expires_from_now(m_events.begin()->expiresFromNow());
- m_deadlineTimer.async_wait(bind(&Scheduler::onEvent, this, _1));
- m_scheduledEvent = m_events.begin();
- }
- else
- {
- m_deadlineTimer.cancel();
- m_scheduledEvent = m_events.end();
+ if (!m_events.empty())
+ {
+ m_deadlineTimer.expires_from_now(m_events.begin()->expiresFromNow());
+ m_deadlineTimer.async_wait(bind(&Scheduler::onEvent, this, _1));
+ m_scheduledEvent = m_events.begin();
+ }
+ else
+ {
+ m_scheduledEvent = m_events.end();
+ }
}
}
@@ -142,40 +148,45 @@
{
return;
}
-
+
+ m_isEventExecuting = true;
+
// process all expired events
time::Point now = time::now();
while(!m_events.empty() && m_events.begin()->m_scheduledTime <= now)
{
EventQueue::iterator head = m_events.begin();
- head->m_event();
+ Event event = head->m_event;
if (head->m_period < 0)
{
- if(head->m_eventId->isValid())
- {
- head->m_eventId->invalidate();
- m_events.erase(head);
- }
+ head->m_eventId->invalidate();
+ m_events.erase(head);
}
else
{
- bool validity = head->m_eventId->isValid();
-
// "reschedule" and update EventId data of the event
EventInfo event(now + head->m_period, *head);
EventQueue::iterator i = m_events.insert(event);
i->m_eventId->reset(i);
- if(validity)
- m_events.erase(head);
+ m_events.erase(head);
}
+
+ event();
}
if (!m_events.empty())
{
m_deadlineTimer.expires_from_now(m_events.begin()->m_scheduledTime - now);
m_deadlineTimer.async_wait(bind(&Scheduler::onEvent, this, _1));
+ m_scheduledEvent = m_events.begin();
}
+ else
+ {
+ m_scheduledEvent = m_events.end();
+ }
+
+ m_isEventExecuting = false;
}
diff --git a/src/util/scheduler.hpp b/src/util/scheduler.hpp
index b1fb596..18c3004 100644
--- a/src/util/scheduler.hpp
+++ b/src/util/scheduler.hpp
@@ -92,6 +92,8 @@
EventQueue m_events;
EventQueue::iterator m_scheduledEvent;
boost::asio::monotonic_deadline_timer m_deadlineTimer;
+
+ bool m_isEventExecuting;
};
} // namespace ndn
diff --git a/src/util/time.hpp b/src/util/time.hpp
index d175964..9af95fc 100644
--- a/src/util/time.hpp
+++ b/src/util/time.hpp
@@ -160,6 +160,13 @@
int64_t m_value;
};
+inline std::ostream&
+operator<<(std::ostream &os, const Duration& duration)
+{
+ os << static_cast<int64_t>(duration) / 1000000000.0 << " s";
+ return os;
+}
+
/**
* \brief Get current time
* \return{ the current time in monotonic clock }