[ndnSIM] util: Redirecting the scheduler of ndn-cxx to the scheduler of NS3
Change-Id: I82fdd94582a731c2238c6645e9ace21a2cacf2de
Refs: #4509
diff --git a/src/util/scheduler.cpp b/src/util/scheduler.cpp
index 167b6e0..513348f 100644
--- a/src/util/scheduler.cpp
+++ b/src/util/scheduler.cpp
@@ -24,142 +24,82 @@
#include <boost/scope_exit.hpp>
+namespace ns3 {
+
+/// @cond include_hidden
+
+template<>
+struct EventMemberImplObjTraits<std::function<void()>> {
+ typedef std::function<void()> T;
+ static T&
+ GetReference(T& p)
+ {
+ return p;
+ }
+};
+
+/// @endcond
+
+} // namespace ns3
+
namespace ndn {
namespace util {
namespace scheduler {
-class EventInfo : noncopyable
-{
-public:
- EventInfo(time::nanoseconds after, const EventCallback& callback)
- : expireTime(time::steady_clock::now() + after)
- , isExpired(false)
- , callback(callback)
- {
- }
-
- time::nanoseconds
- expiresFromNow() const
- {
- return std::max(expireTime - time::steady_clock::now(), time::nanoseconds::zero());
- }
-
-public:
- time::steady_clock::TimePoint expireTime;
- bool isExpired;
- EventCallback callback;
- EventQueue::const_iterator queueIt;
-};
-
-EventId::operator bool() const
-{
- return !m_info.expired() && !m_info.lock()->isExpired;
-}
-
-bool
-EventId::operator==(const EventId& other) const
-{
- return (!(*this) && !other) ||
- !(m_info.owner_before(other.m_info) || other.m_info.owner_before(m_info));
-}
-
-std::ostream&
-operator<<(std::ostream& os, const EventId& eventId)
-{
- return os << eventId.m_info.lock();
-}
-
-bool
-EventQueueCompare::operator()(const shared_ptr<EventInfo>& a, const shared_ptr<EventInfo>& b) const
-{
- return a->expireTime < b->expireTime;
-}
-
Scheduler::Scheduler(boost::asio::io_service& ioService)
- : m_timer(make_unique<detail::SteadyTimer>(ioService))
- , m_isEventExecuting(false)
+ : m_scheduledEvent(m_events.end())
{
}
-Scheduler::~Scheduler() = default;
+Scheduler::~Scheduler()
+{
+ cancelAllEvents();
+}
EventId
-Scheduler::scheduleEvent(time::nanoseconds after, const EventCallback& callback)
+Scheduler::scheduleEvent(const time::nanoseconds& after, const Event& event)
{
- BOOST_ASSERT(callback != nullptr);
+ EventId eventId = std::make_shared<ns3::EventId>();
+ weak_ptr<ns3::EventId> eventWeak = eventId;
+ std::function<void()> eventWithCleanup = [this, event, eventWeak] () {
+ event();
+ shared_ptr<ns3::EventId> eventId = eventWeak.lock();
+ if (eventId != nullptr) {
+ this->m_events.erase(eventId); // remove the event from the set after it is executed
+ }
+ };
- EventQueue::iterator i = m_queue.insert(make_shared<EventInfo>(after, callback));
- (*i)->queueIt = i;
+ ns3::EventId id = ns3::Simulator::Schedule(ns3::NanoSeconds(after.count()),
+ &std::function<void()>::operator(), eventWithCleanup);
+ *eventId = std::move(id);
+ m_events.insert(eventId);
- if (!m_isEventExecuting && i == m_queue.begin()) {
- // the new event is the first one to expire
- this->scheduleNext();
- }
-
- return EventId(*i);
+ return eventId;
}
void
Scheduler::cancelEvent(const EventId& eventId)
{
- shared_ptr<EventInfo> info = eventId.m_info.lock();
- if (info == nullptr || info->isExpired) {
- return; // event already expired or cancelled
- }
-
- if (info->queueIt == m_queue.begin()) {
- m_timer->cancel();
- }
- m_queue.erase(info->queueIt);
-
- if (!m_isEventExecuting) {
- this->scheduleNext();
+ if (eventId != nullptr) {
+ ns3::Simulator::Remove(*eventId);
+ m_events.erase(eventId);
+ const_cast<EventId&>(eventId).reset();
}
}
void
Scheduler::cancelAllEvents()
{
- m_queue.clear();
- m_timer->cancel();
-}
-
-void
-Scheduler::scheduleNext()
-{
- if (!m_queue.empty()) {
- m_timer->expires_from_now((*m_queue.begin())->expiresFromNow());
- m_timer->async_wait(bind(&Scheduler::executeEvent, this, _1));
- }
-}
-
-void
-Scheduler::executeEvent(const boost::system::error_code& error)
-{
- if (error) { // e.g., cancelled
- return;
- }
-
- m_isEventExecuting = true;
-
- BOOST_SCOPE_EXIT(this_) {
- this_->m_isEventExecuting = false;
- this_->scheduleNext();
- } BOOST_SCOPE_EXIT_END
-
- // process all expired events
- auto now = time::steady_clock::now();
- while (!m_queue.empty()) {
- auto head = m_queue.begin();
- shared_ptr<EventInfo> info = *head;
- if (info->expireTime > now) {
- break;
+ for (auto i = m_events.begin(); i != m_events.end(); ) {
+ auto next = i;
+ ++next; // ns3::Simulator::Remove can call cancelEvent
+ if ((*i) != nullptr) {
+ ns3::Simulator::Remove((**i));
+ const_cast<EventId&>(*i).reset();
}
-
- m_queue.erase(head);
- info->isExpired = true;
- info->callback();
+ i = next;
}
+ m_events.clear();
}
} // namespace scheduler