core+daemon: eliminate scheduler::{schedule,cancel} wrappers

Also move core/global-io.hpp to daemon/global.hpp

Refs: #4528, #4883
Change-Id: I0b99029f1a19d7451aab57099cd3303b7eb42ff3
diff --git a/core/common.hpp b/core/common.hpp
index 93c2933..c918724 100644
--- a/core/common.hpp
+++ b/core/common.hpp
@@ -66,7 +66,9 @@
 #include <ndn-cxx/net/face-uri.hpp>
 #include <ndn-cxx/util/backports.hpp>
 #include <ndn-cxx/util/exception.hpp>
+#include <ndn-cxx/util/scheduler.hpp>
 #include <ndn-cxx/util/signal.hpp>
+#include <ndn-cxx/util/time.hpp>
 
 #include <boost/asio.hpp>
 #include <boost/assert.hpp>
@@ -106,6 +108,7 @@
 using ndn::Interest;
 using ndn::Name;
 using ndn::PartialName;
+using ndn::Scheduler;
 
 // Not using a namespace alias (namespace tlv = ndn::tlv), because
 // it doesn't allow NFD to add other members to the namespace
@@ -115,6 +118,7 @@
 
 namespace lp = ndn::lp;
 namespace name = ndn::name;
+namespace scheduler = ndn::scheduler;
 namespace signal = ndn::util::signal;
 namespace time = ndn::time;
 using namespace ndn::time_literals;
diff --git a/core/scheduler.cpp b/core/scheduler.cpp
deleted file mode 100644
index 68f7c75..0000000
--- a/core/scheduler.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2019,  Regents of the University of California,
- *                           Arizona Board of Regents,
- *                           Colorado State University,
- *                           University Pierre & Marie Curie, Sorbonne University,
- *                           Washington University in St. Louis,
- *                           Beijing Institute of Technology,
- *                           The University of Memphis.
- *
- * This file is part of NFD (Named Data Networking Forwarding Daemon).
- * See AUTHORS.md for complete list of NFD authors and contributors.
- *
- * NFD is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "scheduler.hpp"
-#include "global-io.hpp"
-
-namespace nfd {
-namespace scheduler {
-
-static thread_local unique_ptr<Scheduler> g_scheduler;
-
-Scheduler&
-getGlobalScheduler()
-{
-  if (g_scheduler == nullptr) {
-    g_scheduler = make_unique<Scheduler>(getGlobalIoService());
-  }
-  return *g_scheduler;
-}
-
-EventId
-schedule(time::nanoseconds after, const EventCallback& event)
-{
-  return getGlobalScheduler().scheduleEvent(after, event);
-}
-
-#ifdef WITH_TESTS
-void
-resetGlobalScheduler()
-{
-  g_scheduler.reset();
-}
-#endif
-
-} // namespace scheduler
-} // namespace nfd
diff --git a/core/scheduler.hpp b/core/scheduler.hpp
deleted file mode 100644
index 3ad448b..0000000
--- a/core/scheduler.hpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2019,  Regents of the University of California,
- *                           Arizona Board of Regents,
- *                           Colorado State University,
- *                           University Pierre & Marie Curie, Sorbonne University,
- *                           Washington University in St. Louis,
- *                           Beijing Institute of Technology,
- *                           The University of Memphis.
- *
- * This file is part of NFD (Named Data Networking Forwarding Daemon).
- * See AUTHORS.md for complete list of NFD authors and contributors.
- *
- * NFD is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef NFD_CORE_SCHEDULER_HPP
-#define NFD_CORE_SCHEDULER_HPP
-
-#include "common.hpp"
-
-#include <ndn-cxx/util/scheduler.hpp>
-
-namespace nfd {
-namespace scheduler {
-
-using ndn::util::scheduler::Scheduler;
-using ndn::util::scheduler::EventId;
-using ndn::util::scheduler::ScopedEventId;
-using ndn::util::scheduler::EventCallback;
-
-/** \brief Schedule an event.
- */
-EventId
-schedule(time::nanoseconds after, const EventCallback& event);
-
-/** \brief Cancel a scheduled event.
- */
-inline void
-cancel(EventId eventId)
-{
-  eventId.cancel();
-}
-
-} // namespace scheduler
-} // namespace nfd
-
-#endif // NFD_CORE_SCHEDULER_HPP
diff --git a/daemon/face/datagram-transport.hpp b/daemon/face/datagram-transport.hpp
index 501b590..135035f 100644
--- a/daemon/face/datagram-transport.hpp
+++ b/daemon/face/datagram-transport.hpp
@@ -28,7 +28,7 @@
 
 #include "transport.hpp"
 #include "socket-utils.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 #include <array>
 
diff --git a/daemon/face/ethernet-channel.cpp b/daemon/face/ethernet-channel.cpp
index 21949b3..4b5a072 100644
--- a/daemon/face/ethernet-channel.cpp
+++ b/daemon/face/ethernet-channel.cpp
@@ -27,7 +27,7 @@
 #include "ethernet-protocol.hpp"
 #include "generic-link-service.hpp"
 #include "unicast-ethernet-transport.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 #include <boost/range/adaptor/map.hpp>
 #include <pcap/pcap.h>
diff --git a/daemon/face/ethernet-transport.cpp b/daemon/face/ethernet-transport.cpp
index ee7193b..0e69745 100644
--- a/daemon/face/ethernet-transport.cpp
+++ b/daemon/face/ethernet-transport.cpp
@@ -25,7 +25,7 @@
 
 #include "ethernet-transport.hpp"
 #include "ethernet-protocol.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 #include <pcap/pcap.h>
 
diff --git a/daemon/face/face-system.cpp b/daemon/face/face-system.cpp
index 21685f3..260eea7 100644
--- a/daemon/face/face-system.cpp
+++ b/daemon/face/face-system.cpp
@@ -26,7 +26,7 @@
 #include "face-system.hpp"
 #include "protocol-factory.hpp"
 #include "netdev-bound.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 #include "fw/face-table.hpp"
 
 namespace nfd {
diff --git a/daemon/face/internal-face.cpp b/daemon/face/internal-face.cpp
index 8bea03d..f82bd58 100644
--- a/daemon/face/internal-face.cpp
+++ b/daemon/face/internal-face.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2015,  Regents of the University of California,
+/*
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -26,7 +26,7 @@
 #include "internal-face.hpp"
 #include "generic-link-service.hpp"
 #include "internal-transport.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/daemon/face/internal-transport.cpp b/daemon/face/internal-transport.cpp
index 7e7ac3e..5c59ad7 100644
--- a/daemon/face/internal-transport.cpp
+++ b/daemon/face/internal-transport.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,7 +24,7 @@
  */
 
 #include "internal-transport.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/daemon/face/lp-reassembler.cpp b/daemon/face/lp-reassembler.cpp
index 905dc66..918d296 100644
--- a/daemon/face/lp-reassembler.cpp
+++ b/daemon/face/lp-reassembler.cpp
@@ -25,6 +25,7 @@
 
 #include "lp-reassembler.hpp"
 #include "link-service.hpp"
+#include "daemon/global.hpp"
 
 #include <numeric>
 
@@ -113,7 +114,7 @@
   }
 
   // set drop timer
-  pp.dropTimer = scheduler::schedule(m_options.reassemblyTimeout, [=] { timeoutPartialPacket(key); });
+  pp.dropTimer = getScheduler().schedule(m_options.reassemblyTimeout, [=] { timeoutPartialPacket(key); });
 
   return FALSE_RETURN;
 }
diff --git a/daemon/face/lp-reassembler.hpp b/daemon/face/lp-reassembler.hpp
index 21f4e1c..2c5ff91 100644
--- a/daemon/face/lp-reassembler.hpp
+++ b/daemon/face/lp-reassembler.hpp
@@ -26,7 +26,6 @@
 #ifndef NFD_DAEMON_FACE_LP_REASSEMBLER_HPP
 #define NFD_DAEMON_FACE_LP_REASSEMBLER_HPP
 
-#include "core/scheduler.hpp"
 #include "face-log.hpp"
 #include "transport.hpp"
 
@@ -125,8 +124,8 @@
 
 private:
   Options m_options;
-  std::map<Key, PartialPacket> m_partialPackets;
   const LinkService* m_linkService;
+  std::map<Key, PartialPacket> m_partialPackets;
 };
 
 std::ostream&
diff --git a/daemon/face/lp-reliability.cpp b/daemon/face/lp-reliability.cpp
index d46356b..f65d3c3 100644
--- a/daemon/face/lp-reliability.cpp
+++ b/daemon/face/lp-reliability.cpp
@@ -26,6 +26,7 @@
 #include "lp-reliability.hpp"
 #include "generic-link-service.hpp"
 #include "transport.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace face {
@@ -38,7 +39,6 @@
   , m_isIdleAckTimerRunning(false)
 {
   BOOST_ASSERT(m_linkService != nullptr);
-
   BOOST_ASSERT(m_options.idleAckTimerPeriod > 0_ns);
 }
 
@@ -81,7 +81,8 @@
                                                  std::forward_as_tuple(txSeq),
                                                  std::forward_as_tuple(frag));
     unackedFragsIt->second.sendTime = sendTime;
-    unackedFragsIt->second.rtoTimer = scheduler::schedule(m_rto.computeRto(), [=] { onLpPacketLost(txSeq); });
+    unackedFragsIt->second.rtoTimer = getScheduler().schedule(m_rto.computeRto(),
+                                                              [=] { onLpPacketLost(txSeq); });
     unackedFragsIt->second.netPkt = netPkt;
 
     if (m_unackedFrags.size() == 1) {
@@ -199,7 +200,7 @@
   BOOST_ASSERT(!m_isIdleAckTimerRunning);
   m_isIdleAckTimerRunning = true;
 
-  m_idleAckTimer = scheduler::schedule(m_options.idleAckTimerPeriod, [this] {
+  m_idleAckTimer = getScheduler().schedule(m_options.idleAckTimerPeriod, [this] {
     while (!m_ackQueue.empty()) {
       m_linkService->requestIdlePacket();
     }
@@ -304,7 +305,7 @@
     m_linkService->sendLpPacket(lp::Packet(newTxFrag.pkt));
 
     // Start RTO timer for this sequence
-    newTxFrag.rtoTimer = scheduler::schedule(m_rto.computeRto(), [=] { onLpPacketLost(newTxSeq); });
+    newTxFrag.rtoTimer = getScheduler().schedule(m_rto.computeRto(), [=] { onLpPacketLost(newTxSeq); });
   }
 
   return removedThisTxSeq;
diff --git a/daemon/face/lp-reliability.hpp b/daemon/face/lp-reliability.hpp
index 9521183..5018730 100644
--- a/daemon/face/lp-reliability.hpp
+++ b/daemon/face/lp-reliability.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,7 +27,6 @@
 #define NFD_DAEMON_FACE_LP_RELIABILITY_HPP
 
 #include "core/rtt-estimator.hpp"
-#include "core/scheduler.hpp"
 
 #include <ndn-cxx/lp/packet.hpp>
 #include <ndn-cxx/lp/sequence.hpp>
diff --git a/daemon/face/multicast-ethernet-transport.cpp b/daemon/face/multicast-ethernet-transport.cpp
index 2afb793..f0fa5ce 100644
--- a/daemon/face/multicast-ethernet-transport.cpp
+++ b/daemon/face/multicast-ethernet-transport.cpp
@@ -24,7 +24,7 @@
  */
 
 #include "multicast-ethernet-transport.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 #include <cerrno>         // for errno
 #include <cstring>        // for memcpy(), strerror(), strncpy()
diff --git a/daemon/face/stream-transport.hpp b/daemon/face/stream-transport.hpp
index 9daf29e..eb7de92 100644
--- a/daemon/face/stream-transport.hpp
+++ b/daemon/face/stream-transport.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -28,7 +28,7 @@
 
 #include "transport.hpp"
 #include "socket-utils.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 #include <queue>
 
diff --git a/daemon/face/tcp-channel.cpp b/daemon/face/tcp-channel.cpp
index 639b27d..54a620c 100644
--- a/daemon/face/tcp-channel.cpp
+++ b/daemon/face/tcp-channel.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,9 +24,9 @@
  */
 
 #include "tcp-channel.hpp"
-#include "core/global-io.hpp"
 #include "generic-link-service.hpp"
 #include "tcp-transport.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace face {
@@ -84,7 +84,7 @@
   }
 
   auto clientSocket = make_shared<ip::tcp::socket>(std::ref(getGlobalIoService()));
-  auto timeoutEvent = scheduler::schedule(timeout, [=] {
+  auto timeoutEvent = getScheduler().schedule(timeout, [=] {
     handleConnectTimeout(remoteEndpoint, clientSocket, onConnectFailed);
   });
 
@@ -187,7 +187,7 @@
                           const FaceCreatedCallback& onFaceCreated,
                           const FaceCreationFailedCallback& onConnectFailed)
 {
-  scheduler::cancel(connectTimeoutEvent);
+  connectTimeoutEvent.cancel();
 
   if (error) {
     if (error != boost::asio::error::operation_aborted) {
diff --git a/daemon/face/tcp-channel.hpp b/daemon/face/tcp-channel.hpp
index c840695..cb41b2c 100644
--- a/daemon/face/tcp-channel.hpp
+++ b/daemon/face/tcp-channel.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,7 +27,6 @@
 #define NFD_DAEMON_FACE_TCP_CHANNEL_HPP
 
 #include "channel.hpp"
-#include "core/scheduler.hpp"
 
 namespace nfd {
 
diff --git a/daemon/face/tcp-transport.cpp b/daemon/face/tcp-transport.cpp
index 78d7097..4c747be 100644
--- a/daemon/face/tcp-transport.cpp
+++ b/daemon/face/tcp-transport.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,6 +24,7 @@
  */
 
 #include "tcp-transport.hpp"
+#include "daemon/global.hpp"
 
 #if defined(__linux__)
 #include <linux/sockios.h>
@@ -39,7 +40,9 @@
 time::milliseconds TcpTransport::s_maxReconnectWait = 5_min;
 float TcpTransport::s_reconnectWaitMultiplier = 2.0f;
 
-TcpTransport::TcpTransport(protocol::socket&& socket, ndn::nfd::FacePersistency persistency, ndn::nfd::FaceScope faceScope)
+TcpTransport::TcpTransport(protocol::socket&& socket,
+                           ndn::nfd::FacePersistency persistency,
+                           ndn::nfd::FaceScope faceScope)
   : StreamTransport(std::move(socket))
   , m_remoteEndpoint(m_socket.remote_endpoint())
   , m_nextReconnectWait(s_initialReconnectWait)
@@ -103,8 +106,8 @@
     this->setState(TransportState::DOWN);
 
     // cancel all outstanding operations
-    boost::system::error_code error;
-    m_socket.cancel(error);
+    boost::system::error_code ec;
+    m_socket.cancel(ec);
 
     // do this asynchronously because there could be some callbacks still pending
     getGlobalIoService().post([this] { reconnect(); });
@@ -134,7 +137,8 @@
   this->resetReceiveBuffer();
   this->resetSendQueue();
 
-  m_reconnectEvent = scheduler::schedule(m_nextReconnectWait, [this] { this->handleReconnectTimeout(); });
+  m_reconnectEvent = getScheduler().schedule(m_nextReconnectWait,
+                                             [this] { this->handleReconnectTimeout(); });
   m_socket.async_connect(m_remoteEndpoint, [this] (const auto& e) { this->handleReconnect(e); });
 }
 
diff --git a/daemon/face/tcp-transport.hpp b/daemon/face/tcp-transport.hpp
index adf5085..a6a2048 100644
--- a/daemon/face/tcp-transport.hpp
+++ b/daemon/face/tcp-transport.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,7 +27,6 @@
 #define NFD_DAEMON_FACE_TCP_TRANSPORT_HPP
 
 #include "stream-transport.hpp"
-#include "core/scheduler.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/daemon/face/udp-channel.cpp b/daemon/face/udp-channel.cpp
index eb4337f..6497c30 100644
--- a/daemon/face/udp-channel.cpp
+++ b/daemon/face/udp-channel.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -26,7 +26,7 @@
 #include "udp-channel.hpp"
 #include "generic-link-service.hpp"
 #include "unicast-udp-transport.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/daemon/face/udp-factory.cpp b/daemon/face/udp-factory.cpp
index 6730389..2c8cf20 100644
--- a/daemon/face/udp-factory.cpp
+++ b/daemon/face/udp-factory.cpp
@@ -26,7 +26,7 @@
 #include "udp-factory.hpp"
 #include "generic-link-service.hpp"
 #include "multicast-udp-transport.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 #include <boost/range/adaptor/map.hpp>
 #include <boost/range/algorithm/copy.hpp>
diff --git a/daemon/face/unicast-ethernet-transport.cpp b/daemon/face/unicast-ethernet-transport.cpp
index 60059bb..ed61d7a 100644
--- a/daemon/face/unicast-ethernet-transport.cpp
+++ b/daemon/face/unicast-ethernet-transport.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,6 +24,7 @@
  */
 
 #include "unicast-ethernet-transport.hpp"
+#include "daemon/global.hpp"
 
 #include <stdio.h>  // for snprintf()
 
@@ -95,7 +96,7 @@
 void
 UnicastEthernetTransport::scheduleClosureWhenIdle()
 {
-  m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout, [this] {
+  m_closeIfIdleEvent = getScheduler().schedule(m_idleTimeout, [this] {
     if (!hasRecentlyReceived()) {
       NFD_LOG_FACE_INFO("Closing due to inactivity");
       this->close();
diff --git a/daemon/face/unicast-ethernet-transport.hpp b/daemon/face/unicast-ethernet-transport.hpp
index 5a148c9..63d74e9 100644
--- a/daemon/face/unicast-ethernet-transport.hpp
+++ b/daemon/face/unicast-ethernet-transport.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,7 +27,6 @@
 #define NFD_DAEMON_FACE_UNICAST_ETHERNET_TRANSPORT_HPP
 
 #include "ethernet-transport.hpp"
-#include "core/scheduler.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/daemon/face/unicast-udp-transport.cpp b/daemon/face/unicast-udp-transport.cpp
index 062c924..c872c09 100644
--- a/daemon/face/unicast-udp-transport.cpp
+++ b/daemon/face/unicast-udp-transport.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -25,6 +25,7 @@
 
 #include "unicast-udp-transport.hpp"
 #include "udp-protocol.hpp"
+#include "daemon/global.hpp"
 
 #ifdef __linux__
 #include <cerrno>       // for errno
@@ -109,7 +110,7 @@
 void
 UnicastUdpTransport::scheduleClosureWhenIdle()
 {
-  m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout, [this] {
+  m_closeIfIdleEvent = getScheduler().schedule(m_idleTimeout, [this] {
     if (!hasRecentlyReceived()) {
       NFD_LOG_FACE_INFO("Closing due to inactivity");
       this->close();
diff --git a/daemon/face/unicast-udp-transport.hpp b/daemon/face/unicast-udp-transport.hpp
index 03f1c86..fdadfb9 100644
--- a/daemon/face/unicast-udp-transport.hpp
+++ b/daemon/face/unicast-udp-transport.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,7 +27,6 @@
 #define NFD_DAEMON_FACE_UNICAST_UDP_TRANSPORT_HPP
 
 #include "datagram-transport.hpp"
-#include "core/scheduler.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/daemon/face/unix-stream-channel.cpp b/daemon/face/unix-stream-channel.cpp
index 172f797..52a4c99 100644
--- a/daemon/face/unix-stream-channel.cpp
+++ b/daemon/face/unix-stream-channel.cpp
@@ -26,7 +26,7 @@
 #include "unix-stream-channel.hpp"
 #include "generic-link-service.hpp"
 #include "unix-stream-transport.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 #include <boost/filesystem.hpp>
 #include <sys/stat.h> // for chmod()
diff --git a/daemon/face/websocket-channel.cpp b/daemon/face/websocket-channel.cpp
index c4c392b..74b4d39 100644
--- a/daemon/face/websocket-channel.cpp
+++ b/daemon/face/websocket-channel.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -26,7 +26,7 @@
 #include "websocket-channel.hpp"
 #include "generic-link-service.hpp"
 #include "websocket-transport.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/daemon/face/websocket-transport.cpp b/daemon/face/websocket-transport.cpp
index 4262287..b7fdc20 100644
--- a/daemon/face/websocket-transport.cpp
+++ b/daemon/face/websocket-transport.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,6 +24,7 @@
  */
 
 #include "websocket-transport.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace face {
@@ -109,7 +110,7 @@
 void
 WebSocketTransport::schedulePing()
 {
-  m_pingEventId = scheduler::schedule(m_pingInterval, [this] { sendPing(); });
+  m_pingEventId = getScheduler().schedule(m_pingInterval, [this] { sendPing(); });
 }
 
 void
diff --git a/daemon/face/websocket-transport.hpp b/daemon/face/websocket-transport.hpp
index c957802..0bdadb5 100644
--- a/daemon/face/websocket-transport.hpp
+++ b/daemon/face/websocket-transport.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2017,  Regents of the University of California,
+/*
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -28,7 +28,6 @@
 
 #include "transport.hpp"
 #include "websocketpp.hpp"
-#include "core/scheduler.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/daemon/fw/access-strategy.cpp b/daemon/fw/access-strategy.cpp
index e7e0904..eec5a63 100644
--- a/daemon/fw/access-strategy.cpp
+++ b/daemon/fw/access-strategy.cpp
@@ -26,6 +26,7 @@
 #include "access-strategy.hpp"
 #include "algorithm.hpp"
 #include "core/logger.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace fw {
@@ -42,8 +43,7 @@
     NDN_THROW(std::invalid_argument("AccessStrategy does not accept parameters"));
   }
   if (parsed.version && *parsed.version != getStrategyName()[-1].toVersion()) {
-    NDN_THROW(std::invalid_argument(
-      "AccessStrategy does not support version " + to_string(*parsed.version)));
+    NDN_THROW(std::invalid_argument("AccessStrategy does not support version " + to_string(*parsed.version)));
   }
   this->setInstanceName(makeInstanceName(name, getStrategyName()));
 }
@@ -153,7 +153,7 @@
 
   // schedule RTO timeout
   PitInfo* pi = pitEntry->insertStrategyInfo<PitInfo>().first;
-  pi->rtoTimer = scheduler::schedule(rto,
+  pi->rtoTimer = getScheduler().schedule(rto,
       bind(&AccessStrategy::afterRtoTimeout, this, weak_ptr<pit::Entry>(pitEntry),
            inFace.getId(), mi.lastNexthop));
 
diff --git a/daemon/fw/asf-measurements.cpp b/daemon/fw/asf-measurements.cpp
index 17771e0..dde6866 100644
--- a/daemon/fw/asf-measurements.cpp
+++ b/daemon/fw/asf-measurements.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "asf-measurements.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace fw {
@@ -73,7 +74,7 @@
 FaceInfo::~FaceInfo()
 {
   cancelTimeoutEvent();
-  scheduler::cancel(m_measurementExpirationId);
+  m_measurementExpirationId.cancel();
 }
 
 void
@@ -92,7 +93,7 @@
 void
 FaceInfo::cancelTimeoutEvent()
 {
-  scheduler::cancel(m_timeoutEventId);
+  m_timeoutEventId.cancel();
   m_isTimeoutScheduled = false;
 }
 
@@ -114,7 +115,7 @@
 FaceInfo::recordRtt(const shared_ptr<pit::Entry>& pitEntry, const Face& inFace)
 {
   // Calculate RTT
-  pit::OutRecordCollection::const_iterator outRecord = pitEntry->getOutRecord(inFace, 0);
+  auto outRecord = pitEntry->getOutRecord(inFace, 0);
 
   if (outRecord == pitEntry->out_end()) { // no out-record
     NFD_LOG_TRACE(pitEntry->getInterest() << " dataFrom inFace=" << inFace.getId() << " no-out-record");
@@ -122,7 +123,7 @@
   }
 
   time::steady_clock::Duration steadyRtt = time::steady_clock::now() - outRecord->getLastRenewed();
-  RttEstimator::Duration durationRtt = time::duration_cast<RttEstimator::Duration>(steadyRtt);
+  auto durationRtt = time::duration_cast<RttEstimator::Duration>(steadyRtt);
 
   m_rttStats.addRttMeasurement(durationRtt);
 
@@ -148,10 +149,9 @@
 }
 
 FaceInfo*
-NamespaceInfo::getFaceInfo(const fib::Entry& fibEntry, FaceId faceId)
+NamespaceInfo::getFaceInfo(const fib::Entry&, FaceId faceId)
 {
-  FaceInfoTable::iterator it = m_fit.find(faceId);
-
+  auto it = m_fit.find(faceId);
   if (it != m_fit.end()) {
     return &it->second;
   }
@@ -161,10 +161,9 @@
 }
 
 FaceInfo&
-NamespaceInfo::getOrCreateFaceInfo(const fib::Entry& fibEntry, FaceId faceId)
+NamespaceInfo::getOrCreateFaceInfo(const fib::Entry&, FaceId faceId)
 {
-  FaceInfoTable::iterator it = m_fit.find(faceId);
-
+  auto it = m_fit.find(faceId);
   FaceInfo* info = nullptr;
 
   if (it == m_fit.end()) {
@@ -190,10 +189,11 @@
 NamespaceInfo::extendFaceInfoLifetime(FaceInfo& info, FaceId faceId)
 {
   // Cancel previous expiration
-  scheduler::cancel(info.getMeasurementExpirationEventId());
+  info.getMeasurementExpirationEventId().cancel();
 
   // Refresh measurement
-  auto id = scheduler::schedule(AsfMeasurements::MEASUREMENTS_LIFETIME, [=] { expireFaceInfo(faceId); });
+  auto id = getScheduler().schedule(AsfMeasurements::MEASUREMENTS_LIFETIME,
+                                    [=] { expireFaceInfo(faceId); });
   info.setMeasurementExpirationEventId(id);
 }
 
diff --git a/daemon/fw/asf-probing-module.cpp b/daemon/fw/asf-probing-module.cpp
index dd2b537..84055f1 100644
--- a/daemon/fw/asf-probing-module.cpp
+++ b/daemon/fw/asf-probing-module.cpp
@@ -25,6 +25,7 @@
 
 #include "asf-probing-module.hpp"
 #include "algorithm.hpp"
+#include "daemon/global.hpp"
 
 #include <ndn-cxx/util/random.hpp>
 
@@ -50,7 +51,7 @@
   Name prefix = fibEntry.getPrefix();
 
   // Set the probing flag for the namespace to true after passed interval of time
-  scheduler::schedule(interval, [this, prefix] {
+  getScheduler().schedule(interval, [this, prefix] {
     NamespaceInfo* info = m_measurements.getNamespaceInfo(prefix);
 
     if (info == nullptr) {
@@ -65,10 +66,8 @@
 }
 
 Face*
-ProbingModule::getFaceToProbe(const Face& inFace,
-                              const Interest& interest,
-                              const fib::Entry& fibEntry,
-                              const Face& faceUsed)
+ProbingModule::getFaceToProbe(const Face& inFace, const Interest& interest,
+                              const fib::Entry& fibEntry, const Face& faceUsed)
 {
   FaceInfoFacePairSet rankedFaces(
     [] (const auto& pairLhs, const auto& pairRhs) -> bool {
@@ -83,7 +82,7 @@
 
   // Put eligible faces into rankedFaces. If a face does not have an RTT measurement,
   // immediately pick the face for probing
-  for (const fib::NextHop& hop : fibEntry.getNextHops()) {
+  for (const auto& hop : fibEntry.getNextHops()) {
     Face& hopFace = hop.getFace();
 
     // Don't send probe Interest back to the incoming face or use the same face
diff --git a/daemon/fw/asf-strategy.cpp b/daemon/fw/asf-strategy.cpp
index 779daee..46acaf4 100644
--- a/daemon/fw/asf-strategy.cpp
+++ b/daemon/fw/asf-strategy.cpp
@@ -26,6 +26,7 @@
 #include "asf-strategy.hpp"
 #include "algorithm.hpp"
 #include "core/logger.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace fw {
@@ -226,9 +227,8 @@
     NFD_LOG_TRACE("Scheduling timeout for " << fibEntry.getPrefix() << " to: " << egress
                   << " in " << time::duration_cast<time::milliseconds>(timeout) << " ms");
 
-    scheduler::EventId id = scheduler::schedule(timeout,
-        bind(&AsfStrategy::onTimeout, this, interest.getName(), egress.face.getId()));
-
+    auto id = getScheduler().schedule(timeout, bind(&AsfStrategy::onTimeout, this,
+                                                    interest.getName(), egress.face.getId()));
     faceInfo.setTimeoutEvent(id, interest.getName());
   }
 }
diff --git a/daemon/fw/face-table.cpp b/daemon/fw/face-table.cpp
index 7e1880f..a25e107 100644
--- a/daemon/fw/face-table.cpp
+++ b/daemon/fw/face-table.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,8 +24,8 @@
  */
 
 #include "face-table.hpp"
-#include "core/global-io.hpp"
 #include "core/logger.hpp"
+#include "daemon/global.hpp"
 #include "face/channel.hpp"
 
 #include <ndn-cxx/util/concepts.hpp>
diff --git a/daemon/fw/forwarder.cpp b/daemon/fw/forwarder.cpp
index 508a890..328ff31 100644
--- a/daemon/fw/forwarder.cpp
+++ b/daemon/fw/forwarder.cpp
@@ -29,6 +29,7 @@
 #include "best-route-strategy2.hpp"
 #include "strategy.hpp"
 #include "core/logger.hpp"
+#include "daemon/global.hpp"
 #include "table/cleanup.hpp"
 
 #include <ndn-cxx/lp/tags.hpp>
@@ -44,7 +45,7 @@
 }
 
 Forwarder::Forwarder()
-  : m_unsolicitedDataPolicy(new fw::DefaultUnsolicitedDataPolicy())
+  : m_unsolicitedDataPolicy(make_unique<fw::DefaultUnsolicitedDataPolicy>())
   , m_fib(m_nameTree)
   , m_pit(m_nameTree)
   , m_measurements(m_nameTree)
@@ -241,7 +242,7 @@
                 << (pitEntry->isSatisfied ? " satisfied" : " unsatisfied"));
 
   // Dead Nonce List insert if necessary
-  this->insertDeadNonceList(*pitEntry, 0);
+  this->insertDeadNonceList(*pitEntry, nullptr);
 
   // Increment satisfied/unsatisfied Interests counter
   if (pitEntry->isSatisfied) {
@@ -252,7 +253,7 @@
   }
 
   // PIT delete
-  scheduler::cancel(pitEntry->expiryTimer);
+  pitEntry->expiryTimer.cancel();
   m_pit.erase(pitEntry.get());
 }
 
@@ -507,9 +508,8 @@
   BOOST_ASSERT(pitEntry);
   BOOST_ASSERT(duration >= 0_ms);
 
-  scheduler::cancel(pitEntry->expiryTimer);
-
-  pitEntry->expiryTimer = scheduler::schedule(duration, [=] { onInterestFinalize(pitEntry); });
+  pitEntry->expiryTimer.cancel();
+  pitEntry->expiryTimer = getScheduler().schedule(duration, [=] { onInterestFinalize(pitEntry); });
 }
 
 void
diff --git a/daemon/fw/forwarder.hpp b/daemon/fw/forwarder.hpp
index ecc4d72..18ca483 100644
--- a/daemon/fw/forwarder.hpp
+++ b/daemon/fw/forwarder.hpp
@@ -26,11 +26,9 @@
 #ifndef NFD_DAEMON_FW_FORWARDER_HPP
 #define NFD_DAEMON_FW_FORWARDER_HPP
 
-#include "core/common.hpp"
-#include "core/scheduler.hpp"
-#include "forwarder-counters.hpp"
-#include "face-table.hpp"
 #include "face-endpoint.hpp"
+#include "face-table.hpp"
+#include "forwarder-counters.hpp"
 #include "unsolicited-data-policy.hpp"
 #include "table/fib.hpp"
 #include "table/pit.hpp"
@@ -46,9 +44,9 @@
 class Strategy;
 } // namespace fw
 
-/** \brief main class of NFD
+/** \brief Main class of NFD forwarding engine.
  *
- *  Forwarder owns all faces and tables, and implements forwarding pipelines.
+ *  Forwarder owns all faces and tables, and implements the forwarding pipelines.
  */
 class Forwarder
 {
diff --git a/daemon/fw/ncc-strategy.cpp b/daemon/fw/ncc-strategy.cpp
index a6c1e99..5063200 100644
--- a/daemon/fw/ncc-strategy.cpp
+++ b/daemon/fw/ncc-strategy.cpp
@@ -25,6 +25,7 @@
 
 #include "ncc-strategy.hpp"
 #include "algorithm.hpp"
+#include "daemon/global.hpp"
 
 #include <ndn-cxx/util/random.hpp>
 
@@ -90,8 +91,7 @@
     deferRange = time::microseconds((deferFirst.count() + 1) / 2);
     --nUpstreams;
     this->sendInterest(pitEntry, FaceEndpoint(*bestFace, 0), interest);
-    pitEntryInfo->bestFaceTimeout = scheduler::schedule(
-      meInfo.prediction,
+    pitEntryInfo->bestFaceTimeout = getScheduler().schedule(meInfo.prediction,
       bind(&NccStrategy::timeoutOnBestFace, this, weak_ptr<pit::Entry>(pitEntry)));
   }
   else {
@@ -128,7 +128,7 @@
     // this maxInterval would be used to determine when the next doPropagate would happen.
     pitEntryInfo->maxInterval = deferFirst;
   }
-  pitEntryInfo->propagateTimer = scheduler::schedule(deferFirst,
+  pitEntryInfo->propagateTimer = getScheduler().schedule(deferFirst,
     bind(&NccStrategy::doPropagate, this, ingress.face.getId(), weak_ptr<pit::Entry>(pitEntry)));
 }
 
@@ -178,7 +178,7 @@
   if (isForwarded) {
     std::uniform_int_distribution<time::nanoseconds::rep> dist(0, pitEntryInfo->maxInterval.count() - 1);
     time::nanoseconds deferNext(dist(ndn::random::getRandomNumberEngine()));
-    pitEntryInfo->propagateTimer = scheduler::schedule(deferNext,
+    pitEntryInfo->propagateTimer = getScheduler().schedule(deferNext,
       bind(&NccStrategy::doPropagate, this, inFaceId, weak_ptr<pit::Entry>(pitEntry)));
   }
 }
@@ -233,14 +233,14 @@
 
   PitEntryInfo* pitEntryInfo = pitEntry->getStrategyInfo<PitEntryInfo>();
   if (pitEntryInfo != nullptr) {
-    scheduler::cancel(pitEntryInfo->propagateTimer);
+    pitEntryInfo->propagateTimer.cancel();
 
     // Verify that the best face satisfied the interest before canceling the timeout call
     MeasurementsEntryInfo& meInfo = this->getMeasurementsEntryInfo(pitEntry);
     shared_ptr<Face> bestFace = meInfo.getBestFace();
 
     if (bestFace.get() == &ingress.face)
-      scheduler::cancel(pitEntryInfo->bestFaceTimeout);
+      pitEntryInfo->bestFaceTimeout.cancel();
   }
 }
 
@@ -337,8 +337,8 @@
 
 NccStrategy::PitEntryInfo::~PitEntryInfo()
 {
-  scheduler::cancel(this->bestFaceTimeout);
-  scheduler::cancel(this->propagateTimer);
+  bestFaceTimeout.cancel();
+  propagateTimer.cancel();
 }
 
 } // namespace fw
diff --git a/daemon/fw/self-learning-strategy.cpp b/daemon/fw/self-learning-strategy.cpp
index 12e6176..f0eab59 100644
--- a/daemon/fw/self-learning-strategy.cpp
+++ b/daemon/fw/self-learning-strategy.cpp
@@ -27,7 +27,7 @@
 #include "algorithm.hpp"
 
 #include "core/logger.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 #include "rib/service.hpp"
 
 #include <ndn-cxx/lp/empty-value.hpp>
diff --git a/daemon/fw/strategy.hpp b/daemon/fw/strategy.hpp
index bb50556..cc1b2b8 100644
--- a/daemon/fw/strategy.hpp
+++ b/daemon/fw/strategy.hpp
@@ -51,7 +51,9 @@
     BOOST_ASSERT(strategyName.at(-1).isVersion());
     Registry& registry = getRegistry();
     BOOST_ASSERT(registry.count(strategyName) == 0);
-    registry[strategyName] = &make_unique<S, Forwarder&, const Name&>;
+    registry[strategyName] = [] (auto&&... args) {
+      return make_unique<S>(std::forward<decltype(args)>(args)...);
+    };
   }
 
   /** \return whether a strategy instance can be created from \p instanceName
@@ -81,9 +83,9 @@
   listRegistered();
 
 public: // constructor, destructor, strategy name
-  /** \brief construct a strategy instance
+  /** \brief Construct a strategy instance.
    *  \param forwarder a reference to the forwarder, used to enable actions and accessors.
-   *  \note Strategy subclass constructor should not retain a reference to the forwarder.
+   *  \note Strategy subclass constructor must not retain a reference to \p forwarder.
    */
   explicit
   Strategy(Forwarder& forwarder);
diff --git a/core/global-io.cpp b/daemon/global.cpp
similarity index 89%
rename from core/global-io.cpp
rename to daemon/global.cpp
index e906999..bd1dac2 100644
--- a/core/global-io.cpp
+++ b/daemon/global.cpp
@@ -23,11 +23,12 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "global-io.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 
 static thread_local unique_ptr<boost::asio::io_service> g_ioService;
+static thread_local unique_ptr<Scheduler> g_scheduler;
 static boost::asio::io_service* g_mainIoService = nullptr;
 static boost::asio::io_service* g_ribIoService = nullptr;
 
@@ -40,32 +41,24 @@
   return *g_ioService;
 }
 
-#ifdef WITH_TESTS
-namespace scheduler {
-void
-resetGlobalScheduler(); // defined in scheduler.cpp
-} // namespace scheduler
+Scheduler&
+getScheduler()
+{
+  if (g_scheduler == nullptr) {
+    g_scheduler = make_unique<Scheduler>(getGlobalIoService());
+  }
+  return *g_scheduler;
+}
 
+#ifdef WITH_TESTS
 void
 resetGlobalIoService()
 {
-  scheduler::resetGlobalScheduler();
+  g_scheduler.reset();
   g_ioService.reset();
 }
 #endif
 
-void
-setMainIoService(boost::asio::io_service* mainIo)
-{
-  g_mainIoService = mainIo;
-}
-
-void
-setRibIoService(boost::asio::io_service* ribIo)
-{
-  g_ribIoService = ribIo;
-}
-
 boost::asio::io_service&
 getMainIoService()
 {
@@ -81,6 +74,18 @@
 }
 
 void
+setMainIoService(boost::asio::io_service* mainIo)
+{
+  g_mainIoService = mainIo;
+}
+
+void
+setRibIoService(boost::asio::io_service* ribIo)
+{
+  g_ribIoService = ribIo;
+}
+
+void
 runOnMainIoService(const std::function<void()>& f)
 {
   getMainIoService().post(f);
diff --git a/core/global-io.hpp b/daemon/global.hpp
similarity index 75%
rename from core/global-io.hpp
rename to daemon/global.hpp
index 0fb2fbe..05bc577 100644
--- a/core/global-io.hpp
+++ b/daemon/global.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018  Regents of the University of California,
+ * Copyright (c) 2014-2019  Regents of the University of California,
  *                          Arizona Board of Regents,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University,
@@ -22,33 +22,22 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  **/
 
-#ifndef NFD_CORE_GLOBAL_IO_HPP
-#define NFD_CORE_GLOBAL_IO_HPP
+#ifndef NFD_DAEMON_GLOBAL_HPP
+#define NFD_DAEMON_GLOBAL_HPP
 
-#include "common.hpp"
+#include "core/common.hpp"
 
 namespace nfd {
 
-/** \return the global io_service instance
+/** \brief Returns the global io_service instance for the calling thread.
  */
 boost::asio::io_service&
 getGlobalIoService();
 
-void
-setMainIoService(boost::asio::io_service* mainIo);
-
-void
-setRibIoService(boost::asio::io_service* ribIo);
-
-/** \brief run a function on the main io_service instance
+/** \brief Returns the global Scheduler instance for the calling thread.
  */
-void
-runOnMainIoService(const std::function<void()>& f);
-
-/** \brief run a function on the RIB io_service instance
- */
-void
-runOnRibIoService(const std::function<void()>& f);
+Scheduler&
+getScheduler();
 
 boost::asio::io_service&
 getMainIoService();
@@ -56,10 +45,26 @@
 boost::asio::io_service&
 getRibIoService();
 
+void
+setMainIoService(boost::asio::io_service* mainIo);
+
+void
+setRibIoService(boost::asio::io_service* ribIo);
+
+/** \brief Run a function on the main io_service instance.
+ */
+void
+runOnMainIoService(const std::function<void()>& f);
+
+/** \brief Run a function on the RIB io_service instance.
+ */
+void
+runOnRibIoService(const std::function<void()>& f);
+
 #ifdef WITH_TESTS
-/** \brief delete the global io_service instance
+/** \brief Destroy the global io_service instance.
  *
- *  It will be recreated at the next invocation of getGlobalIoService.
+ *  It will be recreated at the next invocation of getGlobalIoService().
  */
 void
 resetGlobalIoService();
@@ -67,4 +72,4 @@
 
 } // namespace nfd
 
-#endif // NFD_CORE_GLOBAL_IO_HPP
+#endif // NFD_DAEMON_GLOBAL_HPP
diff --git a/daemon/main.cpp b/daemon/main.cpp
index 37f34b5..83012fc 100644
--- a/daemon/main.cpp
+++ b/daemon/main.cpp
@@ -26,10 +26,10 @@
 #include "nfd.hpp"
 #include "rib/service.hpp"
 
-#include "core/global-io.hpp"
 #include "core/logger.hpp"
 #include "core/privilege-helper.hpp"
 #include "core/version.hpp"
+#include "daemon/global.hpp"
 
 #include <string.h> // for strsignal()
 
diff --git a/daemon/mgmt/rib-manager.cpp b/daemon/mgmt/rib-manager.cpp
index 1532627..8db60ab 100644
--- a/daemon/mgmt/rib-manager.cpp
+++ b/daemon/mgmt/rib-manager.cpp
@@ -47,8 +47,7 @@
 const Name RibManager::LOCALHOP_TOP_PREFIX = "/localhop/nfd";
 
 RibManager::RibManager(rib::Rib& rib, ndn::Face& face, ndn::KeyChain& keyChain,
-                       ndn::nfd::Controller& nfdController, Dispatcher& dispatcher,
-                       ndn::util::Scheduler& scheduler)
+                       ndn::nfd::Controller& nfdController, Dispatcher& dispatcher, Scheduler& scheduler)
   : ManagerBase(MGMT_MODULE_NAME, dispatcher)
   , m_rib(rib)
   , m_keyChain(keyChain)
@@ -137,7 +136,7 @@
                " origin=" << route.origin << " cost=" << route.cost);
 
   if (expires) {
-    auto event = m_scheduler.scheduleEvent(*expires, [=] { m_rib.onRouteExpiration(name, route); });
+    auto event = m_scheduler.schedule(*expires, [=] { m_rib.onRouteExpiration(name, route); });
     route.setExpirationEvent(event);
     NFD_LOG_TRACE("Scheduled unregistration at: " << *route.expires);
   }
@@ -459,7 +458,7 @@
 void
 RibManager::scheduleActiveFaceFetch(const time::seconds& timeToWait)
 {
-  m_activeFaceFetchEvent = m_scheduler.scheduleEvent(timeToWait, [this] { fetchActiveFaces(); });
+  m_activeFaceFetchEvent = m_scheduler.schedule(timeToWait, [this] { fetchActiveFaces(); });
 }
 
 void
@@ -477,7 +476,7 @@
   for (auto faceId : m_registeredFaces) {
     if (activeFaceIds.count(faceId) == 0) {
       NFD_LOG_DEBUG("Removing invalid face ID: " << faceId);
-      m_scheduler.scheduleEvent(0_ns, [this, faceId] { this->onFaceDestroyedEvent(faceId); });
+      m_scheduler.schedule(0_ns, [this, faceId] { this->onFaceDestroyedEvent(faceId); });
     }
   }
 
@@ -492,7 +491,7 @@
 
   if (notification.getKind() == ndn::nfd::FACE_EVENT_DESTROYED) {
     NFD_LOG_DEBUG("Received notification for destroyed faceId: " << notification.getFaceId());
-    m_scheduler.scheduleEvent(0_ns, [this, id = notification.getFaceId()] { onFaceDestroyedEvent(id); });
+    m_scheduler.schedule(0_ns, [this, id = notification.getFaceId()] { onFaceDestroyedEvent(id); });
   }
 }
 
diff --git a/daemon/mgmt/rib-manager.hpp b/daemon/mgmt/rib-manager.hpp
index 745cfa2..788a1d0 100644
--- a/daemon/mgmt/rib-manager.hpp
+++ b/daemon/mgmt/rib-manager.hpp
@@ -51,8 +51,7 @@
 {
 public:
   RibManager(rib::Rib& rib, ndn::Face& face, ndn::KeyChain& keyChain,
-             ndn::nfd::Controller& nfdController, Dispatcher& dispatcher,
-             ndn::util::Scheduler& scheduler);
+             ndn::nfd::Controller& nfdController, Dispatcher& dispatcher, Scheduler& scheduler);
 
   /**
    * @brief Apply localhost_security configuration.
@@ -246,14 +245,14 @@
   ndn::KeyChain& m_keyChain;
   ndn::nfd::Controller& m_nfdController;
   Dispatcher& m_dispatcher;
-  ndn::util::Scheduler& m_scheduler;
+  Scheduler& m_scheduler;
 
   ndn::nfd::FaceMonitor m_faceMonitor;
   ndn::ValidatorConfig m_localhostValidator;
   ndn::ValidatorConfig m_localhopValidator;
   bool m_isLocalhopEnabled;
 
-  ndn::util::scheduler::ScopedEventId m_activeFaceFetchEvent;
+  scheduler::ScopedEventId m_activeFaceFetchEvent;
   using FaceIdSet = std::set<uint64_t>;
   FaceIdSet m_registeredFaces; ///< contains FaceIds with one or more Routes in the RIB
 };
diff --git a/daemon/nfd.cpp b/daemon/nfd.cpp
index f4d136a..078d987 100644
--- a/daemon/nfd.cpp
+++ b/daemon/nfd.cpp
@@ -24,9 +24,8 @@
  */
 
 #include "nfd.hpp"
-
+#include "global.hpp"
 #include "core/config-file.hpp"
-#include "core/global-io.hpp"
 #include "core/log-config-section.hpp"
 #include "core/privilege-helper.hpp"
 #include "face/face-system.hpp"
@@ -89,7 +88,7 @@
   m_netmon->onNetworkStateChanged.connect([this] {
       // delay stages, so if multiple events are triggered in short sequence,
       // only one auto-detection procedure is triggered
-      m_reloadConfigEvent = scheduler::schedule(5_s,
+      m_reloadConfigEvent = getScheduler().schedule(5_s,
         [this] {
           NFD_LOG_INFO("Network change detected, reloading face section of the config file...");
           this->reloadConfigFileFaceSection();
diff --git a/daemon/nfd.hpp b/daemon/nfd.hpp
index 4aadc18..ba8efd4 100644
--- a/daemon/nfd.hpp
+++ b/daemon/nfd.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,7 +27,6 @@
 #define NFD_DAEMON_NFD_HPP
 
 #include "core/config-file.hpp"
-#include "core/scheduler.hpp"
 
 #include <ndn-cxx/net/network-monitor.hpp>
 #include <ndn-cxx/security/key-chain.hpp>
diff --git a/daemon/rib/readvertise/readvertise.cpp b/daemon/rib/readvertise/readvertise.cpp
index 454ab20..49c3400 100644
--- a/daemon/rib/readvertise/readvertise.cpp
+++ b/daemon/rib/readvertise/readvertise.cpp
@@ -44,7 +44,7 @@
   return std::max(newTime, 0_ms);
 }
 
-Readvertise::Readvertise(Rib& rib, ndn::util::Scheduler& scheduler,
+Readvertise::Readvertise(Rib& rib, Scheduler& scheduler,
                          unique_ptr<ReadvertisePolicy> policy,
                          unique_ptr<ReadvertiseDestination> destination)
   : m_scheduler(scheduler)
@@ -162,14 +162,14 @@
     [=] {
       NFD_LOG_DEBUG("advertise " << rrIt->prefix << " success");
       rrIt->retryDelay = RETRY_DELAY_MIN;
-      rrIt->retryEvt = m_scheduler.scheduleEvent(randomizeTimer(m_policy->getRefreshInterval()),
-                                                 [=] { advertise(rrIt); });
+      rrIt->retryEvt = m_scheduler.schedule(randomizeTimer(m_policy->getRefreshInterval()),
+                                            [=] { advertise(rrIt); });
     },
     [=] (const std::string& msg) {
       NFD_LOG_DEBUG("advertise " << rrIt->prefix << " failure " << msg);
       rrIt->retryDelay = std::min(RETRY_DELAY_MAX, rrIt->retryDelay * 2);
-      rrIt->retryEvt = m_scheduler.scheduleEvent(randomizeTimer(rrIt->retryDelay),
-                                                 [=] { advertise(rrIt); });
+      rrIt->retryEvt = m_scheduler.schedule(randomizeTimer(rrIt->retryDelay),
+                                            [=] { advertise(rrIt); });
     });
 }
 
@@ -192,8 +192,8 @@
     [=] (const std::string& msg) {
       NFD_LOG_DEBUG("withdraw " << rrIt->prefix << " failure " << msg);
       rrIt->retryDelay = std::min(RETRY_DELAY_MAX, rrIt->retryDelay * 2);
-      rrIt->retryEvt = m_scheduler.scheduleEvent(randomizeTimer(rrIt->retryDelay),
-                                                 [=] { withdraw(rrIt); });
+      rrIt->retryEvt = m_scheduler.schedule(randomizeTimer(rrIt->retryDelay),
+                                            [=] { withdraw(rrIt); });
     });
 }
 
diff --git a/daemon/rib/readvertise/readvertise.hpp b/daemon/rib/readvertise/readvertise.hpp
index 80dbbc7..a14d438 100644
--- a/daemon/rib/readvertise/readvertise.hpp
+++ b/daemon/rib/readvertise/readvertise.hpp
@@ -45,8 +45,7 @@
 {
 
 public:
-  Readvertise(Rib& rib,
-              ndn::util::Scheduler& scheduler,
+  Readvertise(Rib& rib, Scheduler& scheduler,
               unique_ptr<ReadvertisePolicy> policy,
               unique_ptr<ReadvertiseDestination> destination);
 
@@ -77,7 +76,7 @@
   static const time::milliseconds RETRY_DELAY_MIN;
   static const time::milliseconds RETRY_DELAY_MAX;
 
-  ndn::util::Scheduler& m_scheduler;
+  Scheduler& m_scheduler;
   unique_ptr<ReadvertisePolicy> m_policy;
   unique_ptr<ReadvertiseDestination> m_destination;
 
diff --git a/daemon/rib/readvertise/readvertised-route.hpp b/daemon/rib/readvertise/readvertised-route.hpp
index 7dc02ae..3749336 100644
--- a/daemon/rib/readvertise/readvertised-route.hpp
+++ b/daemon/rib/readvertise/readvertised-route.hpp
@@ -52,7 +52,7 @@
   mutable ndn::security::SigningInfo signer; ///< signer for commands
   mutable size_t nRibRoutes; ///< number of RIB routes that cause the readvertisement
   mutable time::milliseconds retryDelay; ///< retry interval (not used for refresh)
-  mutable ndn::util::scheduler::ScopedEventId retryEvt; ///< retry or refresh event
+  mutable scheduler::ScopedEventId retryEvt; ///< retry or refresh event
 };
 
 inline bool
diff --git a/daemon/rib/route.hpp b/daemon/rib/route.hpp
index f38fbab..92df470 100644
--- a/daemon/rib/route.hpp
+++ b/daemon/rib/route.hpp
@@ -53,14 +53,14 @@
    */
   Route(const ndn::PrefixAnnouncement& ann, uint64_t faceId);
 
-  const ndn::util::scheduler::EventId&
+  const scheduler::EventId&
   getExpirationEvent() const
   {
     return m_expirationEvent;
   }
 
   void
-  setExpirationEvent(const ndn::util::scheduler::EventId& eid)
+  setExpirationEvent(const scheduler::EventId& eid)
   {
     m_expirationEvent = eid;
   }
@@ -101,7 +101,7 @@
   time::steady_clock::TimePoint annExpires;
 
 private:
-  ndn::util::scheduler::EventId m_expirationEvent;
+  scheduler::EventId m_expirationEvent;
 };
 
 bool
diff --git a/daemon/rib/service.cpp b/daemon/rib/service.cpp
index 35c092d..8405c8e 100644
--- a/daemon/rib/service.cpp
+++ b/daemon/rib/service.cpp
@@ -31,8 +31,8 @@
 #include "readvertise/nfd-rib-readvertise-destination.hpp"
 #include "readvertise/readvertise.hpp"
 
-#include "core/global-io.hpp"
 #include "core/logger.hpp"
+#include "daemon/global.hpp"
 
 #include <boost/property_tree/info_parser.hpp>
 #include <ndn-cxx/transport/tcp-transport.hpp>
diff --git a/daemon/rib/service.hpp b/daemon/rib/service.hpp
index fe9b110..1c07d7e 100644
--- a/daemon/rib/service.hpp
+++ b/daemon/rib/service.hpp
@@ -111,7 +111,7 @@
 
   ndn::KeyChain& m_keyChain;
   ndn::Face m_face;
-  ndn::util::Scheduler m_scheduler;
+  Scheduler m_scheduler;
   ndn::nfd::Controller m_nfdController;
 
   Rib m_rib;
diff --git a/daemon/table/cs-policy-priority-fifo.cpp b/daemon/table/cs-policy-priority-fifo.cpp
index 7984739..f350c72 100644
--- a/daemon/table/cs-policy-priority-fifo.cpp
+++ b/daemon/table/cs-policy-priority-fifo.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -25,6 +25,7 @@
 
 #include "cs-policy-priority-fifo.hpp"
 #include "cs.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace cs {
@@ -117,8 +118,8 @@
   }
   else {
     entryInfo->queueType = QUEUE_FIFO;
-    entryInfo->moveStaleEventId = scheduler::schedule(i->getData().getFreshnessPeriod(),
-                                                      [=] { moveToStaleQueue(i); });
+    entryInfo->moveStaleEventId = getScheduler().schedule(i->getData().getFreshnessPeriod(),
+                                                          [=] { moveToStaleQueue(i); });
   }
 
   Queue& queue = m_queues[entryInfo->queueType];
@@ -133,7 +134,7 @@
 
   EntryInfo* entryInfo = m_entryInfoMap[i];
   if (entryInfo->queueType == QUEUE_FIFO) {
-    scheduler::cancel(entryInfo->moveStaleEventId);
+    entryInfo->moveStaleEventId.cancel();
   }
 
   m_queues[entryInfo->queueType].erase(entryInfo->queueIt);
diff --git a/daemon/table/cs-policy-priority-fifo.hpp b/daemon/table/cs-policy-priority-fifo.hpp
index a914891..39b456f 100644
--- a/daemon/table/cs-policy-priority-fifo.hpp
+++ b/daemon/table/cs-policy-priority-fifo.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,7 +27,6 @@
 #define NFD_DAEMON_TABLE_CS_POLICY_PRIORITY_FIFO_HPP
 
 #include "cs-policy.hpp"
-#include "core/scheduler.hpp"
 
 #include <list>
 
@@ -80,8 +79,7 @@
 public:
   PriorityFifoPolicy();
 
-  virtual
-  ~PriorityFifoPolicy();
+  ~PriorityFifoPolicy() override;
 
 public:
   static const std::string POLICY_NAME;
diff --git a/daemon/table/cs.cpp b/daemon/table/cs.cpp
index 85ef388..a958374 100644
--- a/daemon/table/cs.cpp
+++ b/daemon/table/cs.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -44,10 +44,8 @@
 }
 
 Cs::Cs(size_t nMaxPackets)
-  : m_shouldAdmit(true)
-  , m_shouldServe(true)
 {
-  this->setPolicyImpl(makeDefaultPolicy());
+  setPolicyImpl(makeDefaultPolicy());
   m_policy->setLimit(nMaxPackets);
 }
 
diff --git a/daemon/table/cs.hpp b/daemon/table/cs.hpp
index fc161c5..16e28a5 100644
--- a/daemon/table/cs.hpp
+++ b/daemon/table/cs.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -29,7 +29,7 @@
 #include "cs-policy.hpp"
 #include "cs-internal.hpp"
 #include "cs-entry-impl.hpp"
-#include <ndn-cxx/util/signal.hpp>
+
 #include <boost/iterator/transform_iterator.hpp>
 
 namespace nfd {
@@ -210,8 +210,8 @@
   unique_ptr<Policy> m_policy;
   signal::ScopedConnection m_beforeEvictConnection;
 
-  bool m_shouldAdmit; ///< if false, no Data will be admitted
-  bool m_shouldServe; ///< if false, all lookups will miss
+  bool m_shouldAdmit = true; ///< if false, no Data will be admitted
+  bool m_shouldServe = true; ///< if false, all lookups will miss
 };
 
 } // namespace cs
diff --git a/daemon/table/dead-nonce-list.cpp b/daemon/table/dead-nonce-list.cpp
index 720a415..7d6a908 100644
--- a/daemon/table/dead-nonce-list.cpp
+++ b/daemon/table/dead-nonce-list.cpp
@@ -26,6 +26,7 @@
 #include "dead-nonce-list.hpp"
 #include "core/city-hash.hpp"
 #include "core/logger.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 
@@ -58,14 +59,14 @@
     m_queue.push_back(MARK);
   }
 
-  m_markEvent = scheduler::schedule(m_markInterval, [this] { mark(); });
-  m_adjustCapacityEvent = scheduler::schedule(m_adjustCapacityInterval, [this] { adjustCapacity(); });
+  m_markEvent = getScheduler().schedule(m_markInterval, [this] { mark(); });
+  m_adjustCapacityEvent = getScheduler().schedule(m_adjustCapacityInterval, [this] { adjustCapacity(); });
 }
 
 DeadNonceList::~DeadNonceList()
 {
-  scheduler::cancel(m_markEvent);
-  scheduler::cancel(m_adjustCapacityEvent);
+  m_markEvent.cancel();
+  m_adjustCapacityEvent.cancel();
 
   BOOST_ASSERT_MSG(DEFAULT_LIFETIME >= MIN_LIFETIME, "DEFAULT_LIFETIME is too small");
   static_assert(INITIAL_CAPACITY >= MIN_CAPACITY, "INITIAL_CAPACITY is too small");
@@ -124,7 +125,7 @@
 
   NFD_LOG_TRACE("mark nMarks=" << nMarks);
 
-  m_markEvent = scheduler::schedule(m_markInterval, [this] { mark(); });
+  m_markEvent = getScheduler().schedule(m_markInterval, [this] { mark(); });
 }
 
 void
@@ -145,7 +146,7 @@
   m_actualMarkCounts.clear();
   this->evictEntries();
 
-  m_adjustCapacityEvent = scheduler::schedule(m_adjustCapacityInterval, [this] { adjustCapacity(); });
+  m_adjustCapacityEvent = getScheduler().schedule(m_adjustCapacityInterval, [this] { adjustCapacity(); });
 }
 
 void
diff --git a/daemon/table/dead-nonce-list.hpp b/daemon/table/dead-nonce-list.hpp
index ccbf5a1..dea1d51 100644
--- a/daemon/table/dead-nonce-list.hpp
+++ b/daemon/table/dead-nonce-list.hpp
@@ -27,7 +27,6 @@
 #define NFD_DAEMON_TABLE_DEAD_NONCE_LIST_HPP
 
 #include "core/common.hpp"
-#include "core/scheduler.hpp"
 
 #include <boost/multi_index_container.hpp>
 #include <boost/multi_index/hashed_index.hpp>
diff --git a/daemon/table/measurements-entry.hpp b/daemon/table/measurements-entry.hpp
index 039fe54..fa80327 100644
--- a/daemon/table/measurements-entry.hpp
+++ b/daemon/table/measurements-entry.hpp
@@ -27,7 +27,6 @@
 #define NFD_DAEMON_TABLE_MEASUREMENTS_ENTRY_HPP
 
 #include "strategy-info-host.hpp"
-#include "core/scheduler.hpp"
 
 namespace nfd {
 
diff --git a/daemon/table/measurements.cpp b/daemon/table/measurements.cpp
index 8ab89cc..adfd782 100644
--- a/daemon/table/measurements.cpp
+++ b/daemon/table/measurements.cpp
@@ -27,6 +27,7 @@
 #include "name-tree.hpp"
 #include "pit-entry.hpp"
 #include "fib-entry.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace measurements {
@@ -49,7 +50,7 @@
   entry = nte.getMeasurementsEntry();
 
   entry->m_expiry = time::steady_clock::now() + getInitialLifetime();
-  entry->m_cleanup = scheduler::schedule(getInitialLifetime(), [=] { cleanup(*entry); });
+  entry->m_cleanup = getScheduler().schedule(getInitialLifetime(), [=] { cleanup(*entry); });
 
   return *entry;
 }
@@ -133,9 +134,9 @@
     return;
   }
 
-  scheduler::cancel(entry.m_cleanup);
+  entry.m_cleanup.cancel();
   entry.m_expiry = expiry;
-  entry.m_cleanup = scheduler::schedule(lifetime, [&] { cleanup(entry); });
+  entry.m_cleanup = getScheduler().schedule(lifetime, [&] { cleanup(entry); });
 }
 
 void
diff --git a/daemon/table/pit-entry.hpp b/daemon/table/pit-entry.hpp
index 42334f0..8100b8e 100644
--- a/daemon/table/pit-entry.hpp
+++ b/daemon/table/pit-entry.hpp
@@ -28,7 +28,6 @@
 
 #include "pit-in-record.hpp"
 #include "pit-out-record.hpp"
-#include "core/scheduler.hpp"
 
 #include <list>
 
diff --git a/tests/core/scheduler.t.cpp b/tests/core/scheduler.t.cpp
deleted file mode 100644
index 8e319e0..0000000
--- a/tests/core/scheduler.t.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014-2019,  Regents of the University of California,
- *                           Arizona Board of Regents,
- *                           Colorado State University,
- *                           University Pierre & Marie Curie, Sorbonne University,
- *                           Washington University in St. Louis,
- *                           Beijing Institute of Technology,
- *                           The University of Memphis.
- *
- * This file is part of NFD (Named Data Networking Forwarding Daemon).
- * See AUTHORS.md for complete list of NFD authors and contributors.
- *
- * NFD is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE.  See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "core/scheduler.hpp"
-
-#include "tests/test-common.hpp"
-
-#include <thread>
-
-namespace nfd {
-namespace scheduler {
-// defined in scheduler.cpp
-Scheduler&
-getGlobalScheduler();
-} // namespace scheduler
-
-namespace tests {
-
-BOOST_FIXTURE_TEST_SUITE(TestScheduler, BaseFixture)
-
-BOOST_AUTO_TEST_CASE(ScheduleCancel)
-{
-  int count1 = 0, count2 = 0, count3 = 0;
-
-  scheduler::schedule(500_ms, [&] {
-    BOOST_CHECK_EQUAL(count3, 1);
-    ++count1;
-  });
-
-  scheduler::EventId eid = scheduler::schedule(1_s, [&] { ++count2; });
-  scheduler::cancel(eid);
-
-  scheduler::schedule(250_ms, [&] {
-    BOOST_CHECK_EQUAL(count1, 0);
-    ++count3;
-  });
-
-  {
-    scheduler::ScopedEventId se = scheduler::schedule(50_ms, [&] { ++count2; });
-  } // se goes out of scope, canceling the event
-
-  g_io.run();
-
-  BOOST_CHECK_EQUAL(count1, 1);
-  BOOST_CHECK_EQUAL(count2, 0);
-  BOOST_CHECK_EQUAL(count3, 1);
-}
-
-BOOST_AUTO_TEST_CASE(ThreadLocalScheduler)
-{
-  scheduler::Scheduler* s1 = &scheduler::getGlobalScheduler();
-  scheduler::Scheduler* s2 = nullptr;
-  std::thread t([&s2] { s2 = &scheduler::getGlobalScheduler(); });
-  t.join();
-
-  BOOST_CHECK(s1 != nullptr);
-  BOOST_CHECK(s2 != nullptr);
-  BOOST_CHECK(s1 != s2);
-}
-
-BOOST_AUTO_TEST_SUITE_END() // TestScheduler
-
-} // namespace tests
-} // namespace nfd
diff --git a/tests/daemon/face/channel-fixture.hpp b/tests/daemon/face/channel-fixture.hpp
index 7efedfd..8f94a09 100644
--- a/tests/daemon/face/channel-fixture.hpp
+++ b/tests/daemon/face/channel-fixture.hpp
@@ -27,7 +27,8 @@
 #define NFD_TESTS_DAEMON_FACE_CHANNEL_FIXTURE_HPP
 
 #include "face/channel.hpp"
-#include "tests/limited-io.hpp"
+
+#include "tests/daemon/limited-io.hpp"
 
 #include <type_traits>
 
diff --git a/tests/daemon/face/ethernet-fixture.hpp b/tests/daemon/face/ethernet-fixture.hpp
index 993352d..0a75fcc 100644
--- a/tests/daemon/face/ethernet-fixture.hpp
+++ b/tests/daemon/face/ethernet-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -29,7 +29,7 @@
 #include "face/multicast-ethernet-transport.hpp"
 #include "face/unicast-ethernet-transport.hpp"
 
-#include "tests/limited-io.hpp"
+#include "tests/daemon/limited-io.hpp"
 #include "test-netif.hpp"
 
 namespace nfd {
diff --git a/tests/daemon/face/multicast-ethernet-transport.t.cpp b/tests/daemon/face/multicast-ethernet-transport.t.cpp
index d4e1fce..220274c 100644
--- a/tests/daemon/face/multicast-ethernet-transport.t.cpp
+++ b/tests/daemon/face/multicast-ethernet-transport.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,6 +27,8 @@
 
 #include "ethernet-fixture.hpp"
 
+#include "daemon/global.hpp"
+
 namespace nfd {
 namespace face {
 namespace tests {
@@ -66,7 +68,7 @@
   BOOST_CHECK_EQUAL(transport->getState(), TransportState::UP);
 
   // simulate 'ip link set IFNAME down'
-  scheduler::schedule(10_ms, [=] { netif->setState(ndn::net::InterfaceState::DOWN); });
+  getScheduler().schedule(10_ms, [=] { netif->setState(ndn::net::InterfaceState::DOWN); });
   transport->afterStateChange.connectSingleShot([&] (TransportState oldState, TransportState newState) {
     BOOST_CHECK_EQUAL(oldState, TransportState::UP);
     BOOST_CHECK_EQUAL(newState, TransportState::DOWN);
@@ -76,8 +78,8 @@
   BOOST_CHECK_EQUAL(transport->getState(), TransportState::DOWN);
 
   // simulate 'ip link set IFNAME up'
-  scheduler::schedule(10_ms, [=] { netif->setState(ndn::net::InterfaceState::NO_CARRIER); });
-  scheduler::schedule(80_ms, [=] { netif->setState(ndn::net::InterfaceState::RUNNING); });
+  getScheduler().schedule(10_ms, [=] { netif->setState(ndn::net::InterfaceState::NO_CARRIER); });
+  getScheduler().schedule(80_ms, [=] { netif->setState(ndn::net::InterfaceState::RUNNING); });
   transport->afterStateChange.connectSingleShot([&] (TransportState oldState, TransportState newState) {
     BOOST_CHECK_EQUAL(oldState, TransportState::DOWN);
     BOOST_CHECK_EQUAL(newState, TransportState::UP);
diff --git a/tests/daemon/face/multicast-udp-transport-fixture.hpp b/tests/daemon/face/multicast-udp-transport-fixture.hpp
index 5959821..06455c7 100644
--- a/tests/daemon/face/multicast-udp-transport-fixture.hpp
+++ b/tests/daemon/face/multicast-udp-transport-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -30,7 +30,7 @@
 #include "face/face.hpp"
 
 #include "dummy-receive-link-service.hpp"
-#include "tests/limited-io.hpp"
+#include "tests/daemon/limited-io.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/tests/daemon/face/tcp-factory.t.cpp b/tests/daemon/face/tcp-factory.t.cpp
index d349cf9..3c00134 100644
--- a/tests/daemon/face/tcp-factory.t.cpp
+++ b/tests/daemon/face/tcp-factory.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -27,7 +27,7 @@
 
 #include "face-system-fixture.hpp"
 #include "factory-test-common.hpp"
-#include "tests/limited-io.hpp"
+#include "tests/daemon/limited-io.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/tests/daemon/face/tcp-transport-fixture.hpp b/tests/daemon/face/tcp-transport-fixture.hpp
index 0cfae44..65a4d24 100644
--- a/tests/daemon/face/tcp-transport-fixture.hpp
+++ b/tests/daemon/face/tcp-transport-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -30,7 +30,7 @@
 #include "face/face.hpp"
 
 #include "dummy-receive-link-service.hpp"
-#include "tests/limited-io.hpp"
+#include "tests/daemon/limited-io.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/tests/daemon/face/test-netif.cpp b/tests/daemon/face/test-netif.cpp
index c1a734d..a19623f 100644
--- a/tests/daemon/face/test-netif.cpp
+++ b/tests/daemon/face/test-netif.cpp
@@ -24,7 +24,7 @@
  */
 
 #include "test-netif.hpp"
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/tests/daemon/face/unicast-udp-transport-fixture.hpp b/tests/daemon/face/unicast-udp-transport-fixture.hpp
index e30a6a2..b269a71 100644
--- a/tests/daemon/face/unicast-udp-transport-fixture.hpp
+++ b/tests/daemon/face/unicast-udp-transport-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -30,7 +30,7 @@
 #include "face/face.hpp"
 
 #include "dummy-receive-link-service.hpp"
-#include "tests/limited-io.hpp"
+#include "tests/daemon/limited-io.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/tests/daemon/face/unix-stream-transport-fixture.hpp b/tests/daemon/face/unix-stream-transport-fixture.hpp
index 634bb9a..d131a00 100644
--- a/tests/daemon/face/unix-stream-transport-fixture.hpp
+++ b/tests/daemon/face/unix-stream-transport-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2017,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -30,7 +30,7 @@
 #include "face/face.hpp"
 
 #include "dummy-receive-link-service.hpp"
-#include "tests/limited-io.hpp"
+#include "tests/daemon/limited-io.hpp"
 
 #include <boost/filesystem.hpp>
 
diff --git a/tests/daemon/face/websocket-transport-fixture.hpp b/tests/daemon/face/websocket-transport-fixture.hpp
index 374f922..38ab81c 100644
--- a/tests/daemon/face/websocket-transport-fixture.hpp
+++ b/tests/daemon/face/websocket-transport-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -30,7 +30,7 @@
 #include "face/face.hpp"
 
 #include "dummy-receive-link-service.hpp"
-#include "tests/limited-io.hpp"
+#include "tests/daemon/limited-io.hpp"
 
 namespace nfd {
 namespace face {
diff --git a/tests/daemon/fw/asf-measurements.t.cpp b/tests/daemon/fw/asf-measurements.t.cpp
index cc4c9e4..71491b7 100644
--- a/tests/daemon/fw/asf-measurements.t.cpp
+++ b/tests/daemon/fw/asf-measurements.t.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "fw/asf-measurements.hpp"
+#include "daemon/global.hpp"
 
 #include "tests/daemon/face/dummy-face.hpp"
 #include "tests/test-common.hpp"
@@ -85,7 +86,7 @@
 {
   FaceInfo info;
 
-  scheduler::EventId id = scheduler::schedule(time::seconds(1), []{});
+  auto id = getScheduler().schedule(1_s, []{});
   ndn::Name interestName("/ndn/interest");
 
   // Receive Interest and forward to next hop; should update RTO information
diff --git a/tests/daemon/fw/best-route-strategy2.t.cpp b/tests/daemon/fw/best-route-strategy2.t.cpp
index 80e2603..83f9903 100644
--- a/tests/daemon/fw/best-route-strategy2.t.cpp
+++ b/tests/daemon/fw/best-route-strategy2.t.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "fw/best-route-strategy2.hpp"
+#include "daemon/global.hpp"
 
 #include "tests/test-common.hpp"
 #include "tests/daemon/face/dummy-face.hpp"
@@ -108,17 +109,17 @@
     size_t nSent = strategy.sendInterestHistory.size();
     if (nSent > nSentLast) {
       BOOST_CHECK_EQUAL(nSent - nSentLast, 1);
-      time::steady_clock::TimePoint timeSent = time::steady_clock::now();
+      auto timeSent = time::steady_clock::now();
       BOOST_CHECK_GE(timeSent - timeSentLast, TICK * 8);
       nSentLast = nSent;
       timeSentLast = timeSent;
     }
 
-    retxFrom4Evt = scheduler::schedule(TICK * 5, periodicalRetxFrom4);
+    retxFrom4Evt = getScheduler().schedule(TICK * 5, periodicalRetxFrom4);
   };
   periodicalRetxFrom4();
   this->advanceClocks(TICK, BestRouteStrategy2::RETX_SUPPRESSION_MAX * 16);
-  scheduler::cancel(retxFrom4Evt);
+  retxFrom4Evt.cancel();
 
   // nexthops for accepted retransmissions: follow FIB cost,
   // later forward to an eligible upstream with earliest out-record
diff --git a/tests/daemon/fw/forwarder.t.cpp b/tests/daemon/fw/forwarder.t.cpp
index 2c7c1d2..60c8ea4 100644
--- a/tests/daemon/fw/forwarder.t.cpp
+++ b/tests/daemon/fw/forwarder.t.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "fw/forwarder.hpp"
+#include "daemon/global.hpp"
 
 #include "tests/test-common.hpp"
 #include "tests/daemon/face/dummy-face.hpp"
@@ -545,7 +546,7 @@
   face2->afterSend.connect([face1, face2] (uint32_t pktType) {
     if (pktType == tlv::Interest) {
       auto interest = make_shared<Interest>(face2->sentInterests.back());
-      scheduler::schedule(time::milliseconds(170), [face1, interest] { face1->receiveInterest(*interest); });
+      getScheduler().schedule(170_ms, [face1, interest] { face1->receiveInterest(*interest); });
     }
   });
 
diff --git a/tests/daemon/fw/multicast-strategy.t.cpp b/tests/daemon/fw/multicast-strategy.t.cpp
index 1ee1ae9..e3ed88b 100644
--- a/tests/daemon/fw/multicast-strategy.t.cpp
+++ b/tests/daemon/fw/multicast-strategy.t.cpp
@@ -24,10 +24,11 @@
  */
 
 #include "fw/multicast-strategy.hpp"
-#include "strategy-tester.hpp"
-#include "tests/daemon/face/dummy-face.hpp"
+#include "daemon/global.hpp"
 
+#include "tests/daemon/face/dummy-face.hpp"
 #include "tests/test-common.hpp"
+#include "strategy-tester.hpp"
 
 namespace nfd {
 namespace fw {
@@ -108,17 +109,17 @@
     if (nSent > nSentLast) {
       // Multicast strategy should multicast the interest to other two faces
       BOOST_CHECK_EQUAL(nSent - nSentLast, 2);
-      time::steady_clock::TimePoint timeSent = time::steady_clock::now();
+      auto timeSent = time::steady_clock::now();
       BOOST_CHECK_GE(timeSent - timeSentLast, TICK * 8);
       nSentLast = nSent;
       timeSentLast = timeSent;
     }
 
-    retxFrom4Evt = scheduler::schedule(TICK * 5, periodicalRetxFrom4);
+    retxFrom4Evt = getScheduler().schedule(TICK * 5, periodicalRetxFrom4);
   };
   periodicalRetxFrom4();
   this->advanceClocks(TICK, MulticastStrategy::RETX_SUPPRESSION_MAX * 16);
-  scheduler::cancel(retxFrom4Evt);
+  retxFrom4Evt.cancel();
 }
 
 BOOST_AUTO_TEST_CASE(RejectLoopback)
diff --git a/tests/daemon/fw/ncc-strategy.t.cpp b/tests/daemon/fw/ncc-strategy.t.cpp
index 1b71aa2..4044251 100644
--- a/tests/daemon/fw/ncc-strategy.t.cpp
+++ b/tests/daemon/fw/ncc-strategy.t.cpp
@@ -24,12 +24,10 @@
  */
 
 #include "fw/ncc-strategy.hpp"
+
+#include "tests/daemon/face/dummy-face.hpp"
 #include "strategy-tester.hpp"
 #include "topology-tester.hpp"
-#include "tests/daemon/face/dummy-face.hpp"
-#include "tests/limited-io.hpp"
-
-#include "tests/test-common.hpp"
 
 namespace nfd {
 namespace fw {
diff --git a/tests/daemon/fw/strategy-nack-return.t.cpp b/tests/daemon/fw/strategy-nack-return.t.cpp
index 86c47f6..3d61452 100644
--- a/tests/daemon/fw/strategy-nack-return.t.cpp
+++ b/tests/daemon/fw/strategy-nack-return.t.cpp
@@ -31,12 +31,11 @@
 #include "fw/best-route-strategy2.hpp"
 #include "fw/multicast-strategy.hpp"
 
-#include "tests/test-common.hpp"
-#include "tests/limited-io.hpp"
 #include "choose-strategy.hpp"
 #include "strategy-tester.hpp"
 #include "topology-tester.hpp"
 #include "tests/daemon/face/dummy-face.hpp"
+
 #include <boost/mpl/vector.hpp>
 
 namespace nfd {
diff --git a/tests/daemon/fw/strategy-no-route.t.cpp b/tests/daemon/fw/strategy-no-route.t.cpp
index 3c5be6b..6e8aa8a 100644
--- a/tests/daemon/fw/strategy-no-route.t.cpp
+++ b/tests/daemon/fw/strategy-no-route.t.cpp
@@ -34,11 +34,10 @@
 #include "fw/best-route-strategy2.hpp"
 #include "fw/multicast-strategy.hpp"
 
-#include "tests/test-common.hpp"
-#include "tests/limited-io.hpp"
 #include "choose-strategy.hpp"
 #include "strategy-tester.hpp"
 #include "tests/daemon/face/dummy-face.hpp"
+
 #include <boost/mpl/copy_if.hpp>
 #include <boost/mpl/vector.hpp>
 
diff --git a/tests/daemon/fw/strategy-scope-control.t.cpp b/tests/daemon/fw/strategy-scope-control.t.cpp
index 984c792..c97e8ab 100644
--- a/tests/daemon/fw/strategy-scope-control.t.cpp
+++ b/tests/daemon/fw/strategy-scope-control.t.cpp
@@ -35,11 +35,10 @@
 #include "fw/multicast-strategy.hpp"
 #include "fw/ncc-strategy.hpp"
 
-#include "tests/test-common.hpp"
-#include "tests/limited-io.hpp"
 #include "choose-strategy.hpp"
 #include "strategy-tester.hpp"
 #include "tests/daemon/face/dummy-face.hpp"
+
 #include <boost/mpl/copy_if.hpp>
 #include <boost/mpl/vector.hpp>
 
diff --git a/tests/daemon/fw/strategy-tester.hpp b/tests/daemon/fw/strategy-tester.hpp
index 5b5c98d..f2ac93d 100644
--- a/tests/daemon/fw/strategy-tester.hpp
+++ b/tests/daemon/fw/strategy-tester.hpp
@@ -27,7 +27,8 @@
 #define NFD_TESTS_DAEMON_FW_STRATEGY_TESTER_HPP
 
 #include "fw/strategy.hpp"
-#include "tests/limited-io.hpp"
+
+#include "tests/daemon/limited-io.hpp"
 
 namespace nfd {
 namespace fw {
diff --git a/tests/daemon/fw/topology-tester.cpp b/tests/daemon/fw/topology-tester.cpp
index 15bbc3c..c401aef 100644
--- a/tests/daemon/fw/topology-tester.cpp
+++ b/tests/daemon/fw/topology-tester.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "topology-tester.hpp"
+#include "daemon/global.hpp"
 #include "face/generic-link-service.hpp"
 
 #include <ndn-cxx/encoding/encoding-buffer-fwd.hpp>
@@ -98,7 +99,7 @@
 void
 TopologyLink::scheduleReceive(InternalTransportBase* recipient, const Block& packet)
 {
-  scheduler::schedule(m_delay, [packet, recipient] {
+  getScheduler().schedule(m_delay, [packet, recipient] {
     recipient->receiveFromLink(packet);
   });
 }
@@ -271,8 +272,9 @@
   face.expressInterest(*interest, nullptr, nullptr, nullptr);
 
   if (n > 1) {
-    scheduler::schedule(interval,
-                        [=, &face] { addIntervalConsumer(face, prefix, interval, n - 1, seq); });
+    getScheduler().schedule(interval, [=, &face] {
+      addIntervalConsumer(face, prefix, interval, n - 1, seq);
+    });
   }
 }
 
diff --git a/tests/core/global-io.t.cpp b/tests/daemon/global.t.cpp
similarity index 85%
rename from tests/core/global-io.t.cpp
rename to tests/daemon/global.t.cpp
index 02f5c4c..bdde1ba 100644
--- a/tests/core/global-io.t.cpp
+++ b/tests/daemon/global.t.cpp
@@ -23,27 +23,37 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "core/global-io.hpp"
-#include "core/scheduler.hpp"
+#include "daemon/global.hpp"
 
-#include "tests/rib-io-fixture.hpp"
 #include "tests/test-common.hpp"
+#include "tests/daemon/rib-io-fixture.hpp"
 
 #include <thread>
 
 namespace nfd {
 namespace tests {
 
-BOOST_FIXTURE_TEST_SUITE(TestGlobalIo, BaseFixture)
+BOOST_FIXTURE_TEST_SUITE(TestGlobal, BaseFixture)
 
-BOOST_AUTO_TEST_CASE(ThreadLocalGlobalIoService)
+BOOST_AUTO_TEST_CASE(ThreadLocalIoService)
 {
   boost::asio::io_service* s1 = &getGlobalIoService();
   boost::asio::io_service* s2 = nullptr;
-  std::thread t([&s2] {
-    s2 = &getGlobalIoService();
-  });
 
+  std::thread t([&s2] { s2 = &getGlobalIoService(); });
+  t.join();
+
+  BOOST_CHECK(s1 != nullptr);
+  BOOST_CHECK(s2 != nullptr);
+  BOOST_CHECK(s1 != s2);
+}
+
+BOOST_AUTO_TEST_CASE(ThreadLocalScheduler)
+{
+  scheduler::Scheduler* s1 = &getScheduler();
+  scheduler::Scheduler* s2 = nullptr;
+
+  std::thread t([&s2] { s2 = &getScheduler(); });
   t.join();
 
   BOOST_CHECK(s1 != nullptr);
@@ -115,7 +125,7 @@
 
   hasRibRun = false;
   bool hasMainRun = false;
-  scheduler::schedule(250_ms, [&] {
+  getScheduler().schedule(250_ms, [&] {
     hasMainRun = true;
     runOnRibIoService([&] { hasRibRun = true; });
   });
@@ -127,7 +137,7 @@
   BOOST_CHECK_EQUAL(hasRibRun, true);
 }
 
-BOOST_AUTO_TEST_SUITE_END()
+BOOST_AUTO_TEST_SUITE_END() // TestGlobal
 
 } // namespace tests
 } // namespace nfd
diff --git a/tests/limited-io.cpp b/tests/daemon/limited-io.cpp
similarity index 93%
rename from tests/limited-io.cpp
rename to tests/daemon/limited-io.cpp
index a9da60e..2779b24 100644
--- a/tests/limited-io.cpp
+++ b/tests/daemon/limited-io.cpp
@@ -24,8 +24,8 @@
  */
 
 #include "limited-io.hpp"
-#include "core/global-io.hpp"
 #include "core/logger.hpp"
+#include "daemon/global.hpp"
 
 #include <boost/exception/diagnostic_information.hpp>
 
@@ -39,8 +39,6 @@
 
 LimitedIo::LimitedIo(UnitTestTimeFixture* uttf)
   : m_uttf(uttf)
-  , m_nOpsRemaining(0)
-  , m_isRunning(false)
 {
 }
 
@@ -58,7 +56,7 @@
   m_reason = NO_WORK;
   m_nOpsRemaining = nOpsLimit;
   if (timeLimit >= 0_ns) {
-    m_timeout = scheduler::schedule(timeLimit, [this] { afterTimeout(); });
+    m_timeout = getScheduler().schedule(timeLimit, [this] { afterTimeout(); });
   }
 
   try {
@@ -79,7 +77,7 @@
   }
 
   getGlobalIoService().reset();
-  scheduler::cancel(m_timeout);
+  m_timeout.cancel();
   m_isRunning = false;
 
   return m_reason;
diff --git a/tests/limited-io.hpp b/tests/daemon/limited-io.hpp
similarity index 89%
rename from tests/limited-io.hpp
rename to tests/daemon/limited-io.hpp
index a42a797..7e7ecc4 100644
--- a/tests/limited-io.hpp
+++ b/tests/daemon/limited-io.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -23,11 +23,10 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef NFD_TESTS_LIMITED_IO_HPP
-#define NFD_TESTS_LIMITED_IO_HPP
+#ifndef NFD_TESTS_DAEMON_LIMITED_IO_HPP
+#define NFD_TESTS_DAEMON_LIMITED_IO_HPP
 
-#include "test-common.hpp"
-#include "core/scheduler.hpp"
+#include "tests/test-common.hpp"
 
 #include <exception>
 
@@ -41,12 +40,10 @@
 class LimitedIo : noncopyable
 {
 public:
-  /** \brief construct with UnitTestTimeFixture
-   */
   explicit
   LimitedIo(UnitTestTimeFixture* uttf = nullptr);
 
-  /// indicates why .run returns
+  /// indicates why run() returns
   enum StopReason {
     /// g_io.run() returns normally because there's no work to do
     NO_WORK,
@@ -105,13 +102,13 @@
 private:
   UnitTestTimeFixture* m_uttf;
   StopReason m_reason;
-  int m_nOpsRemaining;
+  int m_nOpsRemaining = 0;
   scheduler::EventId m_timeout;
   std::exception_ptr m_lastException;
-  bool m_isRunning;
+  bool m_isRunning = false;
 };
 
 } // namespace tests
 } // namespace nfd
 
-#endif // NFD_TESTS_LIMITED_IO_HPP
+#endif // NFD_TESTS_DAEMON_LIMITED_IO_HPP
diff --git a/tests/daemon/mgmt/face-manager-command-fixture.cpp b/tests/daemon/mgmt/face-manager-command-fixture.cpp
index 8fcb965..16e99c6 100644
--- a/tests/daemon/mgmt/face-manager-command-fixture.cpp
+++ b/tests/daemon/mgmt/face-manager-command-fixture.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,6 +24,7 @@
  */
 
 #include "face-manager-command-fixture.hpp"
+#include "daemon/global.hpp"
 
 #include <ndn-cxx/net/network-monitor-stub.hpp>
 
diff --git a/tests/daemon/mgmt/manager-common-fixture.cpp b/tests/daemon/mgmt/manager-common-fixture.cpp
index ee8d543..ed4344e 100644
--- a/tests/daemon/mgmt/manager-common-fixture.cpp
+++ b/tests/daemon/mgmt/manager-common-fixture.cpp
@@ -54,7 +54,7 @@
 }
 
 ManagerCommonFixture::ManagerCommonFixture()
-  : m_face(getGlobalIoService(), m_keyChain, {true, true})
+  : m_face(g_io, m_keyChain, {true, true})
   , m_dispatcher(m_face, m_keyChain, ndn::security::SigningInfo())
   , m_responses(m_face.sentData)
 {
diff --git a/tests/daemon/mgmt/rib-manager-sl-announce.t.cpp b/tests/daemon/mgmt/rib-manager-sl-announce.t.cpp
index 452d758..5576878 100644
--- a/tests/daemon/mgmt/rib-manager-sl-announce.t.cpp
+++ b/tests/daemon/mgmt/rib-manager-sl-announce.t.cpp
@@ -163,7 +163,7 @@
 
 private:
   ndn::util::DummyClientFace m_face;
-  ndn::util::Scheduler m_scheduler;
+  Scheduler m_scheduler;
   ndn::nfd::Controller m_nfdController;
   Dispatcher m_dispatcher;
   rib::FibUpdater m_fibUpdater;
diff --git a/tests/daemon/mgmt/rib-manager.t.cpp b/tests/daemon/mgmt/rib-manager.t.cpp
index c3c5dd6..9756a36 100644
--- a/tests/daemon/mgmt/rib-manager.t.cpp
+++ b/tests/daemon/mgmt/rib-manager.t.cpp
@@ -205,7 +205,7 @@
   std::vector<Interest>& m_commands;
   ConfigurationStatus m_status;
 
-  ndn::util::Scheduler m_scheduler;
+  Scheduler m_scheduler;
   ndn::nfd::Controller m_nfdController;
   rib::Rib m_rib;
   rib::FibUpdater m_fibUpdater;
diff --git a/tests/rib-io-fixture.cpp b/tests/daemon/rib-io-fixture.cpp
similarity index 98%
rename from tests/rib-io-fixture.cpp
rename to tests/daemon/rib-io-fixture.cpp
index 8702994..251d6e9 100644
--- a/tests/rib-io-fixture.cpp
+++ b/tests/daemon/rib-io-fixture.cpp
@@ -24,6 +24,7 @@
  */
 
 #include "rib-io-fixture.hpp"
+#include "daemon/global.hpp"
 
 #include <boost/exception/diagnostic_information.hpp>
 
diff --git a/tests/rib-io-fixture.hpp b/tests/daemon/rib-io-fixture.hpp
similarity index 95%
rename from tests/rib-io-fixture.hpp
rename to tests/daemon/rib-io-fixture.hpp
index f2bb892..99d4387 100644
--- a/tests/rib-io-fixture.hpp
+++ b/tests/daemon/rib-io-fixture.hpp
@@ -23,8 +23,8 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef NFD_TESTS_RIB_IO_FIXTURE_HPP
-#define NFD_TESTS_RIB_IO_FIXTURE_HPP
+#ifndef NFD_TESTS_DAEMON_RIB_IO_FIXTURE_HPP
+#define NFD_TESTS_DAEMON_RIB_IO_FIXTURE_HPP
 
 #include "tests/test-common.hpp"
 
@@ -102,4 +102,4 @@
 } // namespace tests
 } // namespace nfd
 
-#endif // NFD_TESTS_RIB_IO_FIXTURE_HPP
+#endif // NFD_TESTS_DAEMON_RIB_IO_FIXTURE_HPP
diff --git a/tests/daemon/rib/readvertise/nfd-rib-readvertise-destination.t.cpp b/tests/daemon/rib/readvertise/nfd-rib-readvertise-destination.t.cpp
index 4967788..d3ec057 100644
--- a/tests/daemon/rib/readvertise/nfd-rib-readvertise-destination.t.cpp
+++ b/tests/daemon/rib/readvertise/nfd-rib-readvertise-destination.t.cpp
@@ -58,7 +58,7 @@
 
 protected:
   ndn::util::DummyClientFace face;
-  ndn::util::Scheduler scheduler;
+  Scheduler scheduler;
   ndn::nfd::Controller controller;
   Rib rib;
   NfdRibReadvertiseDestination dest;
diff --git a/tests/daemon/rib/readvertise/readvertise.t.cpp b/tests/daemon/rib/readvertise/readvertise.t.cpp
index 1ff0f85..f73efbd 100644
--- a/tests/daemon/rib/readvertise/readvertise.t.cpp
+++ b/tests/daemon/rib/readvertise/readvertise.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -159,7 +159,7 @@
 
 private:
   ndn::util::DummyClientFace m_face;
-  ndn::util::Scheduler m_scheduler;
+  Scheduler m_scheduler;
   Rib m_rib;
 };
 
diff --git a/tests/daemon/rib/service.t.cpp b/tests/daemon/rib/service.t.cpp
index 14ee649..156257b 100644
--- a/tests/daemon/rib/service.t.cpp
+++ b/tests/daemon/rib/service.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,8 +24,10 @@
  */
 
 #include "rib/service.hpp"
-#include "tests/rib-io-fixture.hpp"
+#include "daemon/global.hpp"
+
 #include "tests/test-common.hpp"
+#include "tests/daemon/rib-io-fixture.hpp"
 
 namespace nfd {
 namespace rib {
diff --git a/tests/daemon/table/dead-nonce-list.t.cpp b/tests/daemon/table/dead-nonce-list.t.cpp
index 599a7e2..1df1070 100644
--- a/tests/daemon/table/dead-nonce-list.t.cpp
+++ b/tests/daemon/table/dead-nonce-list.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014-2016,  Regents of the University of California,
+/*
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,6 +24,7 @@
  */
 
 #include "table/dead-nonce-list.hpp"
+#include "daemon/global.hpp"
 
 #include "tests/test-common.hpp"
 
@@ -85,8 +86,7 @@
     }
 
     if (addNonceInterval > time::nanoseconds::zero()) {
-      addNonceEvent = scheduler::schedule(addNonceInterval,
-                                          bind(&PeriodicalInsertionFixture::addNonce, this));
+      addNonceEvent = getScheduler().schedule(addNonceInterval, [this] { addNonce(); });
     }
   }
 
diff --git a/tests/other/face-benchmark.cpp b/tests/other/face-benchmark.cpp
index 19aac7c..3ab1dda 100644
--- a/tests/other/face-benchmark.cpp
+++ b/tests/other/face-benchmark.cpp
@@ -23,7 +23,7 @@
  * NFD, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "core/global-io.hpp"
+#include "daemon/global.hpp"
 #include "face/face.hpp"
 #include "face/tcp-channel.hpp"
 #include "face/udp-channel.hpp"
diff --git a/tests/test-common.cpp b/tests/test-common.cpp
index 62e728a..59060d6 100644
--- a/tests/test-common.cpp
+++ b/tests/test-common.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,6 +24,8 @@
  */
 
 #include "test-common.hpp"
+#include "daemon/global.hpp"
+
 #include <ndn-cxx/security/signature-sha256-with-rsa.hpp>
 
 namespace nfd {
diff --git a/tests/test-common.hpp b/tests/test-common.hpp
index c01484c..178502a 100644
--- a/tests/test-common.hpp
+++ b/tests/test-common.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -28,7 +28,7 @@
 
 #include "boost-test.hpp"
 
-#include "core/global-io.hpp"
+#include "core/common.hpp"
 
 #include <ndn-cxx/prefix-announcement.hpp>
 #include <ndn-cxx/util/time-unit-test-clock.hpp>
@@ -157,22 +157,22 @@
  *  \param index name component index
  *  \param a arguments to name::Component constructor
  */
-template<typename...A>
+template<typename... A>
 void
-setNameComponent(Name& name, ssize_t index, const A& ...a)
+setNameComponent(Name& name, ssize_t index, A&&... a)
 {
   Name name2 = name.getPrefix(index);
-  name2.append(name::Component(a...));
+  name2.append(name::Component(std::forward<A>(a)...));
   name2.append(name.getSubName(name2.size()));
-  name = name2;
+  name = std::move(name2);
 }
 
-template<typename Packet, typename...A>
+template<typename Packet, typename... A>
 void
-setNameComponent(Packet& packet, ssize_t index, const A& ...a)
+setNameComponent(Packet& packet, ssize_t index, A&&... a)
 {
   Name name = packet.getName();
-  setNameComponent(name, index, a...);
+  setNameComponent(name, index, std::forward<A>(a)...);
   packet.setName(name);
 }
 
diff --git a/tests/tools/nfdc/status-report.t.cpp b/tests/tools/nfdc/status-report.t.cpp
index 5cd25f9..d15b901 100644
--- a/tests/tools/nfdc/status-report.t.cpp
+++ b/tests/tools/nfdc/status-report.t.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2014-2018,  Regents of the University of California,
+ * Copyright (c) 2014-2019,  Regents of the University of California,
  *                           Arizona Board of Regents,
  *                           Colorado State University,
  *                           University Pierre & Marie Curie, Sorbonne University,
@@ -24,7 +24,6 @@
  */
 
 #include "nfdc/status-report.hpp"
-#include "core/scheduler.hpp"
 
 #include "status-fixture.hpp"
 
@@ -49,9 +48,9 @@
 class DummyModule : public Module
 {
 public:
-  explicit
-  DummyModule(const std::string& moduleName)
+  DummyModule(const std::string& moduleName, boost::asio::io_service& io)
     : m_moduleName(moduleName)
+    , m_scheduler(io)
     , m_res(0)
     , m_delay(time::milliseconds(1))
   {
@@ -70,13 +69,13 @@
   }
 
   void
-  fetchStatus(Controller& controller,
+  fetchStatus(Controller&,
               const std::function<void()>& onSuccess,
               const Controller::DatasetFailCallback& onFailure,
-              const CommandOptions& options) final
+              const CommandOptions&) final
   {
     ++nFetchStatusCalls;
-    scheduler::schedule(m_delay, [=] {
+    m_scheduler.schedule(m_delay, [=] {
       if (m_res == 0) {
         onSuccess();
       }
@@ -103,6 +102,7 @@
 
 private:
   std::string m_moduleName;
+  Scheduler m_scheduler;
   uint32_t m_res;
   time::nanoseconds m_delay;
 };
@@ -133,7 +133,7 @@
   DummyModule&
   addModule(const std::string& moduleName)
   {
-    report.sections.push_back(make_unique<DummyModule>(moduleName));
+    report.sections.push_back(make_unique<DummyModule>(moduleName, g_io));
     return static_cast<DummyModule&>(*report.sections.back());
   }
 
diff --git a/tests/wscript b/tests/wscript
index 7f5b321..9c17ad3 100644
--- a/tests/wscript
+++ b/tests/wscript
@@ -62,6 +62,10 @@
                 src += node.ant_glob('face/unix*.cpp')
             if bld.env.HAVE_WEBSOCKET:
                 src += node.ant_glob('face/websocket*.cpp')
+            if module == 'core' or module == 'tools':
+                src += ['../daemon/global.cpp']
+            if module == 'rib':
+                src += ['daemon/limited-io.cpp', 'daemon/rib-io-fixture.cpp']
 
             objmod = 'daemon' if module == 'rib' else module
             # unit-tests binary for the module
diff --git a/tools/ndn-autoconfig/main.cpp b/tools/ndn-autoconfig/main.cpp
index dd7bec6..e69ef89 100644
--- a/tools/ndn-autoconfig/main.cpp
+++ b/tools/ndn-autoconfig/main.cpp
@@ -24,7 +24,6 @@
  */
 
 #include "procedure.hpp"
-#include "core/scheduler.hpp"
 #include "core/version.hpp"
 
 #include <signal.h>
@@ -88,10 +87,10 @@
     proc.getIoService().stop();
   });
 
-  util::Scheduler sched(proc.getIoService());
-  util::scheduler::ScopedEventId runEvt;
+  Scheduler sched(proc.getIoService());
+  scheduler::ScopedEventId runEvt;
   auto scheduleRerun = [&] (time::nanoseconds delay) {
-    runEvt = sched.scheduleEvent(delay, [&] { proc.runOnce(); });
+    runEvt = sched.schedule(delay, [&] { proc.runOnce(); });
   };
 
   proc.onComplete.connect([&] (bool isSuccess) {