core: global io_service and scheduler

Scheduler and time are imported from ndn-cpp-dev.
Forwarder is using the new scheduler API.
Face system is not transitioned yet.

refs #1290

Change-Id: I5679cb50bbf9890a105f663b038f13951403c2b6
diff --git a/daemon/core/scheduler.cpp b/daemon/core/scheduler.cpp
index a1759ca..439b914 100644
--- a/daemon/core/scheduler.cpp
+++ b/daemon/core/scheduler.cpp
@@ -7,204 +7,24 @@
 #include "scheduler.hpp"
 
 namespace nfd {
+namespace scheduler {
 
-struct EventIdImpl
+static shared_ptr<Scheduler> g_scheduler;
+
+Scheduler&
+getGlobalScheduler()
 {
-  EventIdImpl(const Scheduler::EventQueue::iterator& event)
-    : m_event(event)
-    , m_isValid(true)
-  {
+  if (!static_cast<bool>(g_scheduler)) {
+    g_scheduler = make_shared<Scheduler>(boost::ref(getGlobalIoService()));
   }
-
-  void
-  invalidate()
-  {
-    m_isValid = false;
-  }
-
-  bool
-  isValid() const
-  {
-    return m_isValid;
-  }
-
-  operator const Scheduler::EventQueue::iterator&() const
-  {
-    return m_event;
-  }
-
-  void
-  reset(const Scheduler::EventQueue::iterator& newIterator)
-  {
-    m_event = newIterator;
-    m_isValid = true;
-  }
-
-private:
-  Scheduler::EventQueue::iterator m_event;
-  bool m_isValid;
-};
-
-Scheduler::EventInfo::EventInfo(const time::Duration& after,
-                        const time::Duration& period,
-                        const Event& event)
-  : m_scheduledTime(time::now() + after)
-  , m_period(period)
-  , m_event(event)
-{
-}
-
-Scheduler::EventInfo::EventInfo(const time::Point& when, const EventInfo& previousEvent)
-  : m_scheduledTime(when)
-  , m_period(previousEvent.m_period)
-  , m_event(previousEvent.m_event)
-  , m_eventId(previousEvent.m_eventId)
-{
-}
-
-time::Duration
-Scheduler::EventInfo::expiresFromNow() const
-{
-  time::Point now = time::now();
-  if (now > m_scheduledTime)
-    return time::seconds(0); // event should be scheduled ASAP
-  else
-    return m_scheduledTime - now;
-}
-
-
-Scheduler::Scheduler(boost::asio::io_service& ioService)
-  : m_ioService(ioService)
-  , m_scheduledEvent(m_events.end())
-  , m_deadlineTimer(ioService)
-  , m_isEventExecuting(false)
-{
-}
-
-EventId
-Scheduler::scheduleEvent(const time::Duration& after,
-                         const Event& event)
-{
-  return schedulePeriodicEvent(after, time::nanoseconds(-1), event);
-}
-
-EventId
-Scheduler::schedulePeriodicEvent(const time::Duration& after,
-                                 const time::Duration& period,
-                                 const Event& event)
-{
-  EventQueue::iterator i = m_events.insert(EventInfo(after, period, event));
-  i->m_eventId = make_shared<EventIdImpl>(boost::cref(i));
-
-  if (!m_isEventExecuting)
-    {
-      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;
-}
-  
-void
-Scheduler::cancelEvent(const EventId& eventId)
-{
-  if (!static_cast<bool>(eventId) || !eventId->isValid())
-    return; // event empty, already fired, or cancelled
-  
-  if (static_cast<EventQueue::iterator>(*eventId) != m_scheduledEvent) {
-    m_events.erase(*eventId);
-    eventId->invalidate();
-    return;
-  }
-  
-  m_deadlineTimer.cancel();
-  m_events.erase(static_cast<EventQueue::iterator>(*eventId));
-  eventId->invalidate();
-
-  if (!m_isEventExecuting)
-    {
-      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_deadlineTimer.cancel();
-          m_scheduledEvent = m_events.end();
-        }
-    }
+  return *g_scheduler;
 }
 
 void
-Scheduler::onEvent(const boost::system::error_code& error)
+resetGlobalScheduler()
 {
-  if (error) // e.g., cancelled
-    {
-      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();
-      
-      Event event = head->m_event;
-      if (head->m_period < 0)
-        {
-          head->m_eventId->invalidate();
-          m_events.erase(head);
-        }
-      else
-        {
-          // "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);
-          m_events.erase(head);
-        }
-
-      try
-        {
-          event();
-        }
-      catch(...)
-        {
-          m_isEventExecuting = false;
-          for (EventQueue::iterator i = m_events.begin();
-               i != m_events.end();
-               ++i)
-            {
-              i->m_eventId->invalidate();
-            }
-          m_events.clear();
-          
-          throw;
-        }
-    }
-
-  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;
+  g_scheduler.reset();
 }
 
-
+} // namespace scheduler
 } // namespace nfd