face: deprecate Id types in favor of Handles

This includes:
PendingInterestId => PendingInterestHandle
RegisteredPrefixId => RegisteredPrefixHandle
InterestFilterId => InterestFilterHandle

refs #4316, #3919

Change-Id: I3a2d2f813d36a2d6edbb8c460aaa6e2e380f41e3
diff --git a/ndn-cxx/face.cpp b/ndn-cxx/face.cpp
index 5d4cb65..58c2617 100644
--- a/ndn-cxx/face.cpp
+++ b/ndn-cxx/face.cpp
@@ -192,7 +192,7 @@
 }
 
 void
-Face::removePendingInterest(const PendingInterestId* pendingInterestId)
+Face::cancelPendingInterest(const PendingInterestId* pendingInterestId)
 {
   IO_CAPTURE_WEAK_IMPL(post) {
     impl->asyncRemovePendingInterest(pendingInterestId);
@@ -271,6 +271,14 @@
   return InterestFilterHandle(*this, id);
 }
 
+void
+Face::clearInterestFilter(const InterestFilterId* interestFilterId)
+{
+  IO_CAPTURE_WEAK_IMPL(post) {
+    impl->asyncUnsetInterestFilter(interestFilterId);
+  } IO_CAPTURE_WEAK_IMPL_END
+}
+
 RegisteredPrefixHandle
 Face::registerPrefix(const Name& prefix,
                      const RegisterPrefixSuccessCallback& onSuccess,
@@ -286,25 +294,9 @@
 }
 
 void
-Face::unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId)
-{
-  IO_CAPTURE_WEAK_IMPL(post) {
-    impl->asyncUnregisterPrefix(registeredPrefixId, nullptr, nullptr);
-  } IO_CAPTURE_WEAK_IMPL_END
-}
-
-void
-Face::unsetInterestFilter(const InterestFilterId* interestFilterId)
-{
-  IO_CAPTURE_WEAK_IMPL(post) {
-    impl->asyncUnsetInterestFilter(interestFilterId);
-  } IO_CAPTURE_WEAK_IMPL_END
-}
-
-void
-Face::unregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
-                       const UnregisterPrefixSuccessCallback& onSuccess,
-                       const UnregisterPrefixFailureCallback& onFailure)
+Face::unregisterPrefixImpl(const RegisteredPrefixId* registeredPrefixId,
+                           const UnregisterPrefixSuccessCallback& onSuccess,
+                           const UnregisterPrefixFailureCallback& onFailure)
 {
   IO_CAPTURE_WEAK_IMPL(post) {
     impl->asyncUnregisterPrefix(registeredPrefixId, onSuccess, onFailure);
@@ -352,22 +344,16 @@
 Face::shutdown()
 {
   IO_CAPTURE_WEAK_IMPL(post) {
-    this->asyncShutdown();
+    impl->m_pendingInterestTable.clear();
+    impl->m_registeredPrefixTable.clear();
+
+    if (m_transport->isConnected())
+      m_transport->close();
+
+    impl->m_ioServiceWork.reset();
   } IO_CAPTURE_WEAK_IMPL_END
 }
 
-void
-Face::asyncShutdown()
-{
-  m_impl->m_pendingInterestTable.clear();
-  m_impl->m_registeredPrefixTable.clear();
-
-  if (m_transport->isConnected())
-    m_transport->close();
-
-  m_impl->m_ioServiceWork.reset();
-}
-
 /**
  * @brief extract local fields from NDNLPv2 packet and tag onto a network layer packet
  */
@@ -416,13 +402,13 @@
 }
 
 PendingInterestHandle::PendingInterestHandle(Face& face, const PendingInterestId* id)
-  : CancelHandle([&face, id] { face.removePendingInterest(id); })
+  : CancelHandle([&face, id] { face.cancelPendingInterest(id); })
   , m_id(id)
 {
 }
 
 RegisteredPrefixHandle::RegisteredPrefixHandle(Face& face, const RegisteredPrefixId* id)
-  : CancelHandle([&face, id] { face.unregisterPrefix(id, nullptr, nullptr); })
+  : CancelHandle([&face, id] { face.unregisterPrefixImpl(id, nullptr, nullptr); })
   , m_face(&face)
   , m_id(id)
 {
@@ -441,13 +427,13 @@
     return;
   }
 
-  m_face->unregisterPrefix(m_id, onSuccess, onFailure);
+  m_face->unregisterPrefixImpl(m_id, onSuccess, onFailure);
   m_face = nullptr;
   m_id = nullptr;
 }
 
 InterestFilterHandle::InterestFilterHandle(Face& face, const InterestFilterId* id)
-  : CancelHandle([&face, id] { face.unsetInterestFilter(id); })
+  : CancelHandle([&face, id] { face.clearInterestFilter(id); })
   , m_id(id)
 {
 }
diff --git a/ndn-cxx/face.hpp b/ndn-cxx/face.hpp
index 4f9b4b9..734165d 100644
--- a/ndn-cxx/face.hpp
+++ b/ndn-cxx/face.hpp
@@ -241,11 +241,14 @@
                   const TimeoutCallback& afterTimeout);
 
   /**
-   * @brief Cancel previously expressed Interest
-   * @param pendingInterestId a handle returned by expressInterest.
+   * @deprecated use PendingInterestHandle::cancel()
    */
+  [[deprecated]]
   void
-  removePendingInterest(const PendingInterestId* pendingInterestId);
+  removePendingInterest(const PendingInterestId* pendingInterestId)
+  {
+    cancelPendingInterest(pendingInterestId);
+  }
 
   /**
    * @brief Cancel all previously expressed Interests
@@ -355,48 +358,36 @@
                  uint64_t flags = nfd::ROUTE_FLAG_CHILD_INHERIT);
 
   /**
-   * @brief Remove the registered prefix entry with the registeredPrefixId
-   *
-   * This does not affect another registered prefix with a different registeredPrefixId,
-   * even it if has the same prefix name.  If there is no entry with the
-   * registeredPrefixId, do nothing.
-   *
-   * unsetInterestFilter will use the same credentials as original
-   * setInterestFilter/registerPrefix command
-   *
-   * @param registeredPrefixId a handle returned by registerPrefix
+   * @deprecated use RegisteredPrefixHandle::unregister()
    */
+  [[deprecated]]
   void
-  unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId);
+  unsetInterestFilter(const RegisteredPrefixId* registeredPrefixId)
+  {
+    unregisterPrefixImpl(registeredPrefixId, nullptr, nullptr);
+  }
 
   /**
-   * @brief Remove previously set InterestFilter from library's FIB
-   *
-   * This method always succeeds and will **NOT** send any request to the connected
-   * forwarder.
-   *
-   * @param interestFilterId a handle returned by setInterestFilter.
+   * @deprecated use InterestFilterHandle::cancel()
    */
+  [[deprecated]]
   void
-  unsetInterestFilter(const InterestFilterId* interestFilterId);
+  unsetInterestFilter(const InterestFilterId* interestFilterId)
+  {
+    clearInterestFilter(interestFilterId);
+  }
 
   /**
-   * @brief Unregister prefix from RIB
-   *
-   * unregisterPrefix will use the same credentials as original
-   * setInterestFilter/registerPrefix command
-   *
-   * If registeredPrefixId was obtained using setInterestFilter, the corresponding
-   * InterestFilter will be unset too.
-   *
-   * @param registeredPrefixId a handle returned by registerPrefix
-   * @param onSuccess          Callback to be called when operation succeeds
-   * @param onFailure          Callback to be called when operation fails
+   * @deprecated use RegisteredPrefixHandle::unregister()
    */
+  [[deprecated]]
   void
   unregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
                    const UnregisterPrefixSuccessCallback& onSuccess,
-                   const UnregisterPrefixFailureCallback& onFailure);
+                   const UnregisterPrefixFailureCallback& onFailure)
+  {
+    unregisterPrefixImpl(registeredPrefixId, onSuccess, onFailure);
+  }
 
   /**
    * @brief Publish data packet
@@ -428,8 +419,8 @@
    * To exit cleanly on a producer, unset any Interest filters with unsetInterestFilter() and wait
    * for processEvents() to return. To exit after an error, one can call shutdown().
    * In consumer applications, processEvents() will return when all expressed Interests have been
-   * satisfied, Nacked, or timed out. To terminate earlier, a consumer application should call
-   * removePendingInterests() for all previously expressed and still-pending Interests.
+   * satisfied, Nacked, or timed out. To terminate earlier, a consumer application should cancel
+   * all previously expressed and still-pending Interests.
    *
    * If a positive timeout is specified, then processEvents() will exit after this timeout, provided
    * it is not stopped earlier with shutdown() or when all active events finish. processEvents()
@@ -510,7 +501,15 @@
   onReceiveElement(const Block& blockFromDaemon);
 
   void
-  asyncShutdown();
+  cancelPendingInterest(const PendingInterestId* pendingInterestId);
+
+  void
+  clearInterestFilter(const InterestFilterId* interestFilterId);
+
+  void
+  unregisterPrefixImpl(const RegisteredPrefixId* registeredPrefixId,
+                       const UnregisterPrefixSuccessCallback& onSuccess,
+                       const UnregisterPrefixFailureCallback& onFailure);
 
 private:
   /// the io_service owned by this Face, could be null
@@ -533,6 +532,10 @@
 
   class Impl;
   shared_ptr<Impl> m_impl;
+
+  friend PendingInterestHandle;
+  friend RegisteredPrefixHandle;
+  friend InterestFilterHandle;
 };
 
 /** \brief A handle of pending Interest.
@@ -542,8 +545,6 @@
  *  hdl.cancel(); // cancel the pending Interest
  *  \endcode
  *
- *  \warning Canceling the same pending Interest more than once, using same or different
- *           PendingInterestHandle or ScopedPendingInterestHandle, may trigger undefined behavior.
  *  \warning Canceling a pending Interest after the face has been destructed may trigger undefined
  *           behavior.
  */
@@ -554,6 +555,7 @@
 
   PendingInterestHandle(Face& face, const PendingInterestId* id);
 
+  [[deprecated]]
   operator const PendingInterestId*() const noexcept
   {
     return m_id;
@@ -575,8 +577,6 @@
  *  } // hdl goes out of scope, canceling the pending Interest
  *  \endcode
  *
- *  \warning Canceling the same pending Interest more than once, using same or different
- *           PendingInterestHandle or ScopedPendingInterestHandle, may trigger undefined behavior.
  *  \warning Canceling a pending Interest after the face has been destructed may trigger undefined
  *           behavior.
  */
@@ -595,15 +595,13 @@
 
   RegisteredPrefixHandle(Face& face, const RegisteredPrefixId* id);
 
+  [[deprecated]]
   operator const RegisteredPrefixId*() const noexcept
   {
     return m_id;
   }
 
   /** \brief Unregister the prefix.
-   *  \warning Unregistering the same prefix more than once, using same or different
-   *           RegisteredPrefixHandle or ScopedRegisteredPrefixHandle, may trigger undefined
-   *           behavior.
    *  \warning Unregistering a prefix after the face has been destructed may trigger undefined
    *           behavior.
    */
@@ -629,9 +627,6 @@
  *  } // hdl goes out of scope, unregistering the prefix
  *  \endcode
  *
- *  \warning Unregistering the same prefix more than once, using same or different
- *           RegisteredPrefixHandle or ScopedRegisteredPrefixHandle, may trigger undefined
- *           behavior.
  *  \warning Unregistering a prefix after the face has been destructed may trigger undefined
  *           behavior.
  */
@@ -644,8 +639,6 @@
  *  hdl.cancel(); // unset the Interest filter
  *  \endcode
  *
- *  \warning Unsetting the same Interest filter more than once, using same or different
- *           InterestFilterHandle or ScopedInterestFilterHandle, may trigger undefined behavior.
  *  \warning Unsetting an Interest filter after the face has been destructed may trigger
  *           undefined behavior.
  */
@@ -656,6 +649,7 @@
 
   InterestFilterHandle(Face& face, const InterestFilterId* id);
 
+  [[deprecated]]
   operator const InterestFilterId*() const noexcept
   {
     return m_id;
@@ -677,8 +671,6 @@
  *  } // hdl goes out of scope, unsetting the Interest filter
  *  \endcode
  *
- *  \warning Unsetting the same Interest filter more than once, using same or different
- *           InterestFilterHandle or ScopedInterestFilterHandle, may trigger undefined behavior.
  *  \warning Unsetting an Interest filter after the face has been destructed may trigger
  *           undefined behavior.
  */
diff --git a/ndn-cxx/mgmt/dispatcher.hpp b/ndn-cxx/mgmt/dispatcher.hpp
index a3a2325..c008b59 100644
--- a/ndn-cxx/mgmt/dispatcher.hpp
+++ b/ndn-cxx/mgmt/dispatcher.hpp
@@ -153,14 +153,14 @@
    *  1. if the new top-level prefix overlaps with an existing top-level prefix
    *     (one top-level prefix is a prefix of another top-level prefix), throw std::domain_error
    *  2. if wantRegister is true, invoke face.registerPrefix for the top-level prefix;
-   *     the returned RegisteredPrefixId shall be recorded internally, indexed by the top-level
+   *     the returned RegisteredPrefixHandle shall be recorded internally, indexed by the top-level
    *     prefix
    *  3. foreach relPrefix from ControlCommands and StatusDatasets,
    *     join the top-level prefix with the relPrefix to obtain the full prefix,
    *     and invoke non-registering overload of face.setInterestFilter,
    *     with the InterestHandler set to an appropriate private method to handle incoming Interests
    *     for the ControlCommand or StatusDataset;
-   *     the returned InterestFilterId shall be recorded internally, indexed by the top-level
+   *     the returned InterestFilterHandle shall be recorded internally, indexed by the top-level
    *     prefix
    */
   void
@@ -172,10 +172,8 @@
    *
    *  Procedure for removing a top-level prefix:
    *  1. if the top-level prefix has not been added, abort these steps
-   *  2. if the top-level prefix has been added with wantRegister,
-   *     invoke face.unregisterPrefix with the RegisteredPrefixId
-   *  3. foreach InterestFilterId recorded during addTopPrefix,
-   *     invoke face.unsetInterestFilter with the InterestFilterId
+   *  2. if the top-level prefix has been added with wantRegister, unregister the prefix
+   *  3. unset each Interest filter recorded during addTopPrefix,
    */
   void
   removeTopPrefix(const Name& prefix);
diff --git a/ndn-cxx/util/notification-subscriber.cpp b/ndn-cxx/util/notification-subscriber.cpp
index 2ae1e52..0794e39 100644
--- a/ndn-cxx/util/notification-subscriber.cpp
+++ b/ndn-cxx/util/notification-subscriber.cpp
@@ -42,7 +42,6 @@
   , m_lastNackSequenceNum(std::numeric_limits<uint64_t>::max())
   , m_attempts(1)
   , m_scheduler(face.getIoService())
-  , m_lastInterestId(nullptr)
   , m_interestLifetime(interestLifetime)
 {
 }
@@ -66,9 +65,7 @@
     return;
   m_isRunning = false;
 
-  if (m_lastInterestId != nullptr)
-    m_face.removePendingInterest(m_lastInterestId);
-  m_lastInterestId = nullptr;
+  m_lastInterest.cancel();
 }
 
 void
@@ -102,10 +99,10 @@
 void
 NotificationSubscriberBase::sendInterest(const Interest& interest)
 {
-  m_lastInterestId = m_face.expressInterest(interest,
-                                            [this] (const auto&, const auto& d) { this->afterReceiveData(d); },
-                                            [this] (const auto&, const auto& n) { this->afterReceiveNack(n); },
-                                            [this] (const auto&) { this->afterTimeout(); });
+  m_lastInterest = m_face.expressInterest(interest,
+                                          [this] (const auto&, const auto& d) { this->afterReceiveData(d); },
+                                          [this] (const auto&, const auto& n) { this->afterReceiveNack(n); },
+                                          [this] (const auto&) { this->afterTimeout(); });
 }
 
 bool
diff --git a/ndn-cxx/util/notification-subscriber.hpp b/ndn-cxx/util/notification-subscriber.hpp
index d2bd2fc..2cc5f42 100644
--- a/ndn-cxx/util/notification-subscriber.hpp
+++ b/ndn-cxx/util/notification-subscriber.hpp
@@ -139,7 +139,7 @@
   uint64_t m_attempts;
   util::scheduler::Scheduler m_scheduler;
   util::scheduler::ScopedEventId m_nackEvent;
-  const PendingInterestId* m_lastInterestId;
+  ScopedPendingInterestHandle m_lastInterest;
   time::milliseconds m_interestLifetime;
 };
 
diff --git a/ndn-cxx/util/segment-fetcher.cpp b/ndn-cxx/util/segment-fetcher.cpp
index bc537a5..2d70aee 100644
--- a/ndn-cxx/util/segment-fetcher.cpp
+++ b/ndn-cxx/util/segment-fetcher.cpp
@@ -104,12 +104,7 @@
     return;
   }
 
-  for (const auto& pendingSegment : m_pendingSegments | boost::adaptors::map_values) {
-    m_face.removePendingInterest(pendingSegment.id);
-    if (pendingSegment.timeoutEvent) {
-      m_scheduler.cancelEvent(pendingSegment.timeoutEvent);
-    }
-  }
+  m_pendingSegments.clear(); // cancels pending Interests and timeout events
   m_face.getIoService().post([self = std::move(m_this)] {});
 }
 
@@ -254,11 +249,10 @@
     return;
   }
 
-  afterSegmentReceived(data);
-
-  // Cancel timeout event
   pendingSegmentIt->second.timeoutEvent.cancel();
 
+  afterSegmentReceived(data);
+
   m_validator.validate(data,
                        bind(&SegmentFetcher::afterValidationSuccess, this, _1, origInterest,
                             pendingSegmentIt, weakSelf),
@@ -476,15 +470,14 @@
 
 void
 SegmentFetcher::updateRetransmittedSegment(uint64_t segmentNum,
-                                           const PendingInterestId* pendingInterest,
+                                           const PendingInterestHandle& pendingInterest,
                                            scheduler::EventId timeoutEvent)
 {
   auto pendingSegmentIt = m_pendingSegments.find(segmentNum);
   BOOST_ASSERT(pendingSegmentIt != m_pendingSegments.end());
   BOOST_ASSERT(pendingSegmentIt->second.state == SegmentState::InRetxQueue);
   pendingSegmentIt->second.state = SegmentState::Retransmitted;
-  m_face.removePendingInterest(pendingSegmentIt->second.id);
-  pendingSegmentIt->second.id = pendingInterest;
+  pendingSegmentIt->second.hdl = pendingInterest; // cancels previous pending Interest via scoped handle
   pendingSegmentIt->second.timeoutEvent = timeoutEvent;
 }
 
@@ -493,11 +486,7 @@
 {
   for (auto it = m_pendingSegments.begin(); it != m_pendingSegments.end();) {
     if (it->first >= static_cast<uint64_t>(m_nSegments)) {
-      m_face.removePendingInterest(it->second.id);
-      if (it->second.timeoutEvent) {
-        m_scheduler.cancelEvent(it->second.timeoutEvent);
-      }
-      it = m_pendingSegments.erase(it);
+      it = m_pendingSegments.erase(it); // cancels pending Interest and timeout event
       BOOST_ASSERT(m_nSegmentsInFlight > 0);
       m_nSegmentsInFlight--;
     }
diff --git a/ndn-cxx/util/segment-fetcher.hpp b/ndn-cxx/util/segment-fetcher.hpp
index ca2e3a8..9a3d5fd 100644
--- a/ndn-cxx/util/segment-fetcher.hpp
+++ b/ndn-cxx/util/segment-fetcher.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2013-2018, Regents of the University of California,
+ * Copyright (c) 2013-2019, Regents of the University of California,
  *                          Colorado State University,
  *                          University Pierre & Marie Curie, Sorbonne University.
  *
@@ -227,7 +227,7 @@
 
   void
   updateRetransmittedSegment(uint64_t segmentNum,
-                             const PendingInterestId* pendingInterest,
+                             const PendingInterestHandle& pendingInterest,
                              scheduler::EventId timeoutEvent);
 
   void
@@ -284,8 +284,8 @@
   public:
     SegmentState state;
     time::steady_clock::TimePoint sendTime;
-    const PendingInterestId* id;
-    scheduler::EventId timeoutEvent;
+    ScopedPendingInterestHandle hdl;
+    scheduler::ScopedEventId timeoutEvent;
   };
 
 NDN_CXX_PUBLIC_WITH_TESTS_ELSE_PRIVATE: