face: rework list structures
refs #3919
Change-Id: Ib734923ef5f701d733d5b0f915183f10434ce30b
diff --git a/ndn-cxx/face.cpp b/ndn-cxx/face.cpp
index a225a9d..70fd8db 100644
--- a/ndn-cxx/face.cpp
+++ b/ndn-cxx/face.cpp
@@ -179,7 +179,7 @@
const NackCallback& afterNacked,
const TimeoutCallback& afterTimeout)
{
- auto id = m_impl->generatePendingInterestId();
+ auto id = m_impl->m_pendingInterestTable.allocateId();
auto interest2 = make_shared<Interest>(interest);
interest2->getNonce();
@@ -188,14 +188,14 @@
impl->asyncExpressInterest(id, interest2, afterSatisfied, afterNacked, afterTimeout);
} IO_CAPTURE_WEAK_IMPL_END
- return PendingInterestHandle(*this, id);
+ return PendingInterestHandle(*this, reinterpret_cast<const PendingInterestId*>(id));
}
void
Face::cancelPendingInterest(const PendingInterestId* pendingInterestId)
{
IO_CAPTURE_WEAK_IMPL(post) {
- impl->asyncRemovePendingInterest(pendingInterestId);
+ impl->asyncRemovePendingInterest(reinterpret_cast<RecordId>(pendingInterestId));
} IO_CAPTURE_WEAK_IMPL_END
}
@@ -230,52 +230,44 @@
}
RegisteredPrefixHandle
-Face::setInterestFilter(const InterestFilter& interestFilter,
- const InterestCallback& onInterest,
+Face::setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest,
const RegisterPrefixFailureCallback& onFailure,
- const security::SigningInfo& signingInfo,
- uint64_t flags)
+ const security::SigningInfo& signingInfo, uint64_t flags)
{
- return setInterestFilter(interestFilter, onInterest, nullptr, onFailure, signingInfo, flags);
+ return setInterestFilter(filter, onInterest, nullptr, onFailure, signingInfo, flags);
}
RegisteredPrefixHandle
-Face::setInterestFilter(const InterestFilter& interestFilter,
- const InterestCallback& onInterest,
+Face::setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest,
const RegisterPrefixSuccessCallback& onSuccess,
const RegisterPrefixFailureCallback& onFailure,
- const security::SigningInfo& signingInfo,
- uint64_t flags)
+ const security::SigningInfo& signingInfo, uint64_t flags)
{
- auto filter = make_shared<InterestFilterRecord>(interestFilter, onInterest);
-
nfd::CommandOptions options;
options.setSigningInfo(signingInfo);
- auto id = m_impl->registerPrefix(interestFilter.getPrefix(), filter,
- onSuccess, onFailure, flags, options);
- return RegisteredPrefixHandle(*this, id);
+ auto id = m_impl->registerPrefix(filter.getPrefix(), onSuccess, onFailure, flags, options,
+ filter, onInterest);
+ return RegisteredPrefixHandle(*this, reinterpret_cast<const RegisteredPrefixId*>(id));
}
InterestFilterHandle
-Face::setInterestFilter(const InterestFilter& interestFilter,
- const InterestCallback& onInterest)
+Face::setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest)
{
- auto filter = make_shared<InterestFilterRecord>(interestFilter, onInterest);
+ auto id = m_impl->m_interestFilterTable.allocateId();
IO_CAPTURE_WEAK_IMPL(post) {
- impl->asyncSetInterestFilter(filter);
+ impl->asyncSetInterestFilter(id, filter, onInterest);
} IO_CAPTURE_WEAK_IMPL_END
- auto id = reinterpret_cast<const InterestFilterId*>(filter.get());
- return InterestFilterHandle(*this, id);
+ return InterestFilterHandle(*this, reinterpret_cast<const InterestFilterId*>(id));
}
void
Face::clearInterestFilter(const InterestFilterId* interestFilterId)
{
IO_CAPTURE_WEAK_IMPL(post) {
- impl->asyncUnsetInterestFilter(interestFilterId);
+ impl->asyncUnsetInterestFilter(reinterpret_cast<RecordId>(interestFilterId));
} IO_CAPTURE_WEAK_IMPL_END
}
@@ -289,8 +281,8 @@
nfd::CommandOptions options;
options.setSigningInfo(signingInfo);
- auto id = m_impl->registerPrefix(prefix, nullptr, onSuccess, onFailure, flags, options);
- return RegisteredPrefixHandle(*this, id);
+ auto id = m_impl->registerPrefix(prefix, onSuccess, onFailure, flags, options, nullopt, nullptr);
+ return RegisteredPrefixHandle(*this, reinterpret_cast<const RegisteredPrefixId*>(id));
}
void
@@ -299,7 +291,8 @@
const UnregisterPrefixFailureCallback& onFailure)
{
IO_CAPTURE_WEAK_IMPL(post) {
- impl->asyncUnregisterPrefix(registeredPrefixId, onSuccess, onFailure);
+ impl->asyncUnregisterPrefix(reinterpret_cast<RecordId>(registeredPrefixId),
+ onSuccess, onFailure);
} IO_CAPTURE_WEAK_IMPL_END
}
diff --git a/ndn-cxx/face.hpp b/ndn-cxx/face.hpp
index 734165d..c14e556 100644
--- a/ndn-cxx/face.hpp
+++ b/ndn-cxx/face.hpp
@@ -273,18 +273,17 @@
* different callbacks, use one registerPrefix call, followed (in onSuccess callback) by
* a series of setInterestFilter calls.
*
- * @param interestFilter Interest filter (prefix part will be registered with the forwarder)
- * @param onInterest A callback to be called when a matching interest is received
- * @param onFailure A callback to be called when prefixRegister command fails
- * @param flags (optional) RIB flags
- * @param signingInfo (optional) Signing parameters. When omitted, a default parameters
- * used in the signature will be used.
+ * @param filter Interest filter (prefix part will be registered with the forwarder)
+ * @param onInterest A callback to be called when a matching interest is received
+ * @param onFailure A callback to be called when prefixRegister command fails
+ * @param signingInfo Signing parameters. When omitted, a default parameters used in the
+ * signature will be used.
+ * @param flags Prefix registration flags
*
- * @return A handle for unregistering the prefix.
+ * @return A handle for unregistering the prefix and unsetting the Interest filter.
*/
RegisteredPrefixHandle
- setInterestFilter(const InterestFilter& interestFilter,
- const InterestCallback& onInterest,
+ setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest,
const RegisterPrefixFailureCallback& onFailure,
const security::SigningInfo& signingInfo = security::SigningInfo(),
uint64_t flags = nfd::ROUTE_FLAG_CHILD_INHERIT);
@@ -299,19 +298,18 @@
* different callbacks, use one registerPrefix call, followed (in onSuccess callback) by
* a series of setInterestFilter calls.
*
- * @param interestFilter Interest filter (prefix part will be registered with the forwarder)
- * @param onInterest A callback to be called when a matching interest is received
- * @param onSuccess A callback to be called when prefixRegister command succeeds
- * @param onFailure A callback to be called when prefixRegister command fails
- * @param flags (optional) RIB flags
- * @param signingInfo (optional) Signing parameters. When omitted, a default parameters
- * used in the signature will be used.
+ * @param filter Interest filter (prefix part will be registered with the forwarder)
+ * @param onInterest A callback to be called when a matching interest is received
+ * @param onSuccess A callback to be called when prefixRegister command succeeds
+ * @param onFailure A callback to be called when prefixRegister command fails
+ * @param signingInfo Signing parameters. When omitted, a default parameters used in the
+ * signature will be used.
+ * @param flags Prefix registration flags
*
- * @return A handle for unregistering the prefix.
+ * @return A handle for unregistering the prefix and unsetting the Interest filter.
*/
RegisteredPrefixHandle
- setInterestFilter(const InterestFilter& interestFilter,
- const InterestCallback& onInterest,
+ setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest,
const RegisterPrefixSuccessCallback& onSuccess,
const RegisterPrefixFailureCallback& onFailure,
const security::SigningInfo& signingInfo = security::SigningInfo(),
@@ -320,7 +318,7 @@
/**
* @brief Set InterestFilter to dispatch incoming matching interest to onInterest callback
*
- * @param interestFilter Interest
+ * @param filter Interest filter
* @param onInterest A callback to be called when a matching interest is received
*
* This method modifies library's FIB only, and does not register the prefix with the
@@ -330,8 +328,7 @@
* @return A handle for unsetting the Interest filter.
*/
InterestFilterHandle
- setInterestFilter(const InterestFilter& interestFilter,
- const InterestCallback& onInterest);
+ setInterestFilter(const InterestFilter& filter, const InterestCallback& onInterest);
/**
* @brief Register prefix with the connected NDN forwarder
@@ -343,8 +340,8 @@
* @param prefix A prefix to register with the connected NDN forwarder
* @param onSuccess A callback to be called when prefixRegister command succeeds
* @param onFailure A callback to be called when prefixRegister command fails
- * @param signingInfo (optional) Signing parameters. When omitted, a default parameters
- * used in the signature will be used.
+ * @param signingInfo Signing parameters. When omitted, a default parameters used in the
+ * signature will be used.
* @param flags Prefix registration flags
*
* @return A handle for unregistering the prefix.
diff --git a/ndn-cxx/impl/container-with-on-empty-signal.hpp b/ndn-cxx/impl/container-with-on-empty-signal.hpp
deleted file mode 100644
index b40b19e..0000000
--- a/ndn-cxx/impl/container-with-on-empty-signal.hpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2013-2018 Regents of the University of California.
- *
- * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
- *
- * ndn-cxx library is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free Software
- * Foundation, either version 3 of the License, or (at your option) any later version.
- *
- * ndn-cxx library 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 Lesser General Public License for more details.
- *
- * You should have received copies of the GNU General Public License and GNU Lesser
- * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
- */
-
-#ifndef NDN_IMPL_CONTAINER_WITH_ON_EMPTY_SIGNAL_HPP
-#define NDN_IMPL_CONTAINER_WITH_ON_EMPTY_SIGNAL_HPP
-
-#include "ndn-cxx/detail/common.hpp"
-#include "ndn-cxx/util/signal.hpp"
-
-namespace ndn {
-
-/**
- * @brief A container that emits onEmpty signal when it becomes empty
- */
-template<class T>
-class ContainerWithOnEmptySignal
-{
-public:
- typedef std::list<T> Base;
- typedef typename Base::value_type value_type;
- typedef typename Base::iterator iterator;
-
- iterator
- begin()
- {
- return m_container.begin();
- }
-
- iterator
- end()
- {
- return m_container.end();
- }
-
- size_t
- size()
- {
- return m_container.size();
- }
-
- bool
- empty()
- {
- return m_container.empty();
- }
-
- iterator
- erase(iterator item)
- {
- iterator next = m_container.erase(item);
- if (empty()) {
- this->onEmpty();
- }
- return next;
- }
-
- void
- clear()
- {
- m_container.clear();
- this->onEmpty();
- }
-
- std::pair<iterator, bool>
- insert(const value_type& value)
- {
- return {m_container.insert(end(), value), true};
- }
-
- template<class Predicate>
- void remove_if(Predicate p)
- {
- m_container.remove_if(p);
- if (empty()) {
- this->onEmpty();
- }
- }
-
-public:
- Base m_container;
-
- /**
- * @brief Signal to be fired when container becomes empty
- */
- util::Signal<ContainerWithOnEmptySignal<T>> onEmpty;
-};
-
-} // namespace ndn
-
-#endif // NDN_IMPL_CONTAINER_WITH_ON_EMPTY_SIGNAL_HPP
diff --git a/ndn-cxx/impl/face-impl.hpp b/ndn-cxx/impl/face-impl.hpp
index e8219ed..4a9c56a 100644
--- a/ndn-cxx/impl/face-impl.hpp
+++ b/ndn-cxx/impl/face-impl.hpp
@@ -23,7 +23,6 @@
#define NDN_IMPL_FACE_IMPL_HPP
#include "ndn-cxx/face.hpp"
-#include "ndn-cxx/impl/container-with-on-empty-signal.hpp"
#include "ndn-cxx/impl/lp-field-tag.hpp"
#include "ndn-cxx/impl/pending-interest.hpp"
#include "ndn-cxx/impl/registered-prefix.hpp"
@@ -59,15 +58,14 @@
class Face::Impl : noncopyable
{
public:
- using PendingInterestTable = ContainerWithOnEmptySignal<shared_ptr<PendingInterest>>;
- using InterestFilterTable = std::list<shared_ptr<InterestFilterRecord>>;
- using RegisteredPrefixTable = ContainerWithOnEmptySignal<shared_ptr<RegisteredPrefix>>;
+ using PendingInterestTable = RecordContainer<PendingInterest>;
+ using InterestFilterTable = RecordContainer<InterestFilterRecord>;
+ using RegisteredPrefixTable = RecordContainer<RegisteredPrefix>;
explicit
Impl(Face& face)
: m_face(face)
, m_scheduler(m_face.getIoService())
- , m_lastPendingInterestId(0)
{
auto postOnEmptyPitOrNoRegisteredPrefixes = [this] {
this->m_face.getIoService().post([this] { this->onEmptyPitOrNoRegisteredPrefixes(); });
@@ -82,16 +80,8 @@
}
public: // consumer
- const PendingInterestId*
- generatePendingInterestId()
- {
- auto id = ++m_lastPendingInterestId;
- return reinterpret_cast<const PendingInterestId*>(id);
- }
-
void
- asyncExpressInterest(const PendingInterestId* id,
- shared_ptr<const Interest> interest,
+ asyncExpressInterest(RecordId id, shared_ptr<const Interest> interest,
const DataCallback& afterSatisfied,
const NackCallback& afterNacked,
const TimeoutCallback& afterTimeout)
@@ -100,28 +90,23 @@
this->ensureConnected(true);
const Interest& interest2 = *interest;
- auto i = m_pendingInterestTable.insert(make_shared<PendingInterest>(
- id, std::move(interest), afterSatisfied, afterNacked, afterTimeout, ref(m_scheduler))).first;
- // In dispatchInterest, an InterestCallback may respond with Data right away and delete
- // the PendingInterestTable entry. shared_ptr is retained to ensure PendingInterest instance
- // remains valid in this case.
- shared_ptr<PendingInterest> entry = *i;
- entry->setDeleter([this, i] { m_pendingInterestTable.erase(i); });
+ auto& entry = m_pendingInterestTable.put(id, std::move(interest), afterSatisfied, afterNacked,
+ afterTimeout, ref(m_scheduler));
lp::Packet lpPacket;
addFieldFromTag<lp::NextHopFaceIdField, lp::NextHopFaceIdTag>(lpPacket, interest2);
addFieldFromTag<lp::CongestionMarkField, lp::CongestionMarkTag>(lpPacket, interest2);
- entry->recordForwarding();
+ entry.recordForwarding();
m_face.m_transport->send(finishEncoding(std::move(lpPacket), interest2.wireEncode(),
'I', interest2.getName()));
- dispatchInterest(*entry, interest2);
+ dispatchInterest(entry, interest2);
}
void
- asyncRemovePendingInterest(const PendingInterestId* pendingInterestId)
+ asyncRemovePendingInterest(RecordId id)
{
- m_pendingInterestTable.remove_if(MatchPendingInterestId(pendingInterestId));
+ m_pendingInterestTable.erase(id);
}
void
@@ -136,24 +121,22 @@
satisfyPendingInterests(const Data& data)
{
bool hasAppMatch = false, hasForwarderMatch = false;
- for (auto i = m_pendingInterestTable.begin(); i != m_pendingInterestTable.end(); ) {
- shared_ptr<PendingInterest> entry = *i;
- if (!entry->getInterest()->matchesData(data)) {
- ++i;
- continue;
+ m_pendingInterestTable.removeIf([&] (PendingInterest& entry) {
+ if (!entry.getInterest()->matchesData(data)) {
+ return false;
}
+ NDN_LOG_DEBUG(" satisfying " << *entry.getInterest() << " from " << entry.getOrigin());
- NDN_LOG_DEBUG(" satisfying " << *entry->getInterest() << " from " << entry->getOrigin());
- i = m_pendingInterestTable.erase(i);
-
- if (entry->getOrigin() == PendingInterestOrigin::APP) {
+ if (entry.getOrigin() == PendingInterestOrigin::APP) {
hasAppMatch = true;
- entry->invokeDataCallback(data);
+ entry.invokeDataCallback(data);
}
else {
hasForwarderMatch = true;
}
- }
+
+ return true;
+ });
// if Data matches no pending Interest record, it is sent to the forwarder as unsolicited Data
return hasForwarderMatch || !hasAppMatch;
}
@@ -164,29 +147,25 @@
nackPendingInterests(const lp::Nack& nack)
{
optional<lp::Nack> outNack;
- for (auto i = m_pendingInterestTable.begin(); i != m_pendingInterestTable.end(); ) {
- shared_ptr<PendingInterest> entry = *i;
- if (!nack.getInterest().matchesInterest(*entry->getInterest())) {
- ++i;
- continue;
+ m_pendingInterestTable.removeIf([&] (PendingInterest& entry) {
+ if (!nack.getInterest().matchesInterest(*entry.getInterest())) {
+ return false;
}
+ NDN_LOG_DEBUG(" nacking " << *entry.getInterest() << " from " << entry.getOrigin());
- NDN_LOG_DEBUG(" nacking " << *entry->getInterest() << " from " << entry->getOrigin());
-
- optional<lp::Nack> outNack1 = entry->recordNack(nack);
+ optional<lp::Nack> outNack1 = entry.recordNack(nack);
if (!outNack1) {
- ++i;
- continue;
+ return false;
}
- if (entry->getOrigin() == PendingInterestOrigin::APP) {
- entry->invokeNackCallback(*outNack1);
+ if (entry.getOrigin() == PendingInterestOrigin::APP) {
+ entry.invokeNackCallback(*outNack1);
}
else {
outNack = outNack1;
}
- i = m_pendingInterestTable.erase(i);
- }
+ return true;
+ });
// send "least severe" Nack from any PendingInterest record originated from forwarder, because
// it is unimportant to consider Nack reason for the unlikely case when forwarder sends multiple
// Interests to an app in a short while
@@ -195,21 +174,20 @@
public: // producer
void
- asyncSetInterestFilter(shared_ptr<InterestFilterRecord> interestFilterRecord)
+ asyncSetInterestFilter(RecordId id, const InterestFilter& filter,
+ const InterestCallback& onInterest)
{
- NDN_LOG_INFO("setting InterestFilter: " << interestFilterRecord->getFilter());
- m_interestFilterTable.push_back(std::move(interestFilterRecord));
+ NDN_LOG_INFO("setting InterestFilter: " << filter);
+ m_interestFilterTable.put(id, filter, onInterest);
}
void
- asyncUnsetInterestFilter(const InterestFilterId* interestFilterId)
+ asyncUnsetInterestFilter(RecordId id)
{
- InterestFilterTable::iterator i = std::find_if(m_interestFilterTable.begin(),
- m_interestFilterTable.end(),
- MatchInterestFilterId(interestFilterId));
- if (i != m_interestFilterTable.end()) {
- NDN_LOG_INFO("unsetting InterestFilter: " << (*i)->getFilter());
- m_interestFilterTable.erase(i);
+ const InterestFilterRecord* record = m_interestFilterTable.get(id);
+ if (record != nullptr) {
+ NDN_LOG_INFO("unsetting InterestFilter: " << record->getFilter());
+ m_interestFilterTable.erase(id);
}
}
@@ -217,27 +195,21 @@
processIncomingInterest(shared_ptr<const Interest> interest)
{
const Interest& interest2 = *interest;
- auto i = m_pendingInterestTable.insert(make_shared<PendingInterest>(
- std::move(interest), ref(m_scheduler))).first;
- // In dispatchInterest, an InterestCallback may respond with Data right away and delete
- // the PendingInterestTable entry. shared_ptr is retained to ensure PendingInterest instance
- // remains valid in this case.
- shared_ptr<PendingInterest> entry = *i;
- entry->setDeleter([this, i] { m_pendingInterestTable.erase(i); });
-
- this->dispatchInterest(*entry, interest2);
+ auto& entry = m_pendingInterestTable.insert(std::move(interest), ref(m_scheduler));
+ dispatchInterest(entry, interest2);
}
void
dispatchInterest(PendingInterest& entry, const Interest& interest)
{
- for (const auto& filter : m_interestFilterTable) {
- if (filter->doesMatch(entry)) {
- NDN_LOG_DEBUG(" matches " << filter->getFilter());
- entry.recordForwarding();
- filter->invokeInterestCallback(interest);
+ m_interestFilterTable.forEach([&] (const InterestFilterRecord& filter) {
+ if (!filter.doesMatch(entry)) {
+ return;
}
- }
+ NDN_LOG_DEBUG(" matches " << filter.getFilter());
+ entry.recordForwarding();
+ filter.invokeInterestCallback(interest);
+ });
}
void
@@ -280,98 +252,76 @@
}
public: // prefix registration
- const RegisteredPrefixId*
+ RecordId
registerPrefix(const Name& prefix,
- shared_ptr<InterestFilterRecord> filter,
const RegisterPrefixSuccessCallback& onSuccess,
const RegisterPrefixFailureCallback& onFailure,
- uint64_t flags,
- const nfd::CommandOptions& options)
+ uint64_t flags, const nfd::CommandOptions& options,
+ const optional<InterestFilter>& filter, const InterestCallback& onInterest)
{
NDN_LOG_INFO("registering prefix: " << prefix);
- auto record = make_shared<RegisteredPrefix>(prefix, filter, options);
+ auto id = m_registeredPrefixTable.allocateId();
- nfd::ControlParameters params;
- params.setName(prefix);
- params.setFlags(flags);
m_face.m_nfdController->start<nfd::RibRegisterCommand>(
- params,
- [=] (const nfd::ControlParameters&) { this->afterPrefixRegistered(record, onSuccess); },
+ nfd::ControlParameters().setName(prefix).setFlags(flags),
+ [=] (const nfd::ControlParameters&) {
+ NDN_LOG_INFO("registered prefix: " << prefix);
+
+ RecordId filterId = 0;
+ if (filter) {
+ NDN_LOG_INFO("setting InterestFilter: " << *filter);
+ InterestFilterRecord& filterRecord = m_interestFilterTable.insert(*filter, onInterest);
+ filterId = filterRecord.getId();
+ }
+
+ m_registeredPrefixTable.put(id, prefix, options, filterId);
+
+ if (onSuccess != nullptr) {
+ onSuccess(prefix);
+ }
+ },
[=] (const nfd::ControlResponse& resp) {
- NDN_LOG_INFO("register prefix failed: " << record->getPrefix());
- onFailure(record->getPrefix(), resp.getText());
+ NDN_LOG_INFO("register prefix failed: " << prefix);
+ onFailure(prefix, resp.getText());
},
options);
- return reinterpret_cast<const RegisteredPrefixId*>(record.get());
+ return id;
}
void
- afterPrefixRegistered(shared_ptr<RegisteredPrefix> registeredPrefix,
- const RegisterPrefixSuccessCallback& onSuccess)
- {
- NDN_LOG_INFO("registered prefix: " << registeredPrefix->getPrefix());
- m_registeredPrefixTable.insert(registeredPrefix);
-
- if (registeredPrefix->getFilter() != nullptr) {
- // it was a combined operation
- m_interestFilterTable.push_back(registeredPrefix->getFilter());
- }
-
- if (onSuccess != nullptr) {
- onSuccess(registeredPrefix->getPrefix());
- }
- }
-
- void
- asyncUnregisterPrefix(const RegisteredPrefixId* registeredPrefixId,
+ asyncUnregisterPrefix(RecordId id,
const UnregisterPrefixSuccessCallback& onSuccess,
const UnregisterPrefixFailureCallback& onFailure)
{
- auto i = std::find_if(m_registeredPrefixTable.begin(),
- m_registeredPrefixTable.end(),
- MatchRegisteredPrefixId(registeredPrefixId));
- if (i != m_registeredPrefixTable.end()) {
- RegisteredPrefix& record = **i;
- const shared_ptr<InterestFilterRecord>& filter = record.getFilter();
-
- if (filter != nullptr) {
- // it was a combined operation
- m_interestFilterTable.remove(filter);
- }
-
- NDN_LOG_INFO("unregistering prefix: " << record.getPrefix());
-
- nfd::ControlParameters params;
- params.setName(record.getPrefix());
- m_face.m_nfdController->start<nfd::RibUnregisterCommand>(
- params,
- [=] (const nfd::ControlParameters&) { this->finalizeUnregisterPrefix(i, onSuccess); },
- [=] (const nfd::ControlResponse& resp) {
- NDN_LOG_INFO("unregister prefix failed: " << params.getName());
- onFailure(resp.getText());
- },
- record.getCommandOptions());
- }
- else {
+ const RegisteredPrefix* record = m_registeredPrefixTable.get(id);
+ if (record == nullptr) {
if (onFailure != nullptr) {
- onFailure("Unrecognized PrefixId");
+ onFailure("Unrecognized RegisteredPrefixHandle");
}
+ return;
}
- // there cannot be two registered prefixes with the same id
- }
-
- void
- finalizeUnregisterPrefix(RegisteredPrefixTable::iterator item,
- const UnregisterPrefixSuccessCallback& onSuccess)
- {
- NDN_LOG_INFO("unregistered prefix: " << (*item)->getPrefix());
- m_registeredPrefixTable.erase(item);
-
- if (onSuccess != nullptr) {
- onSuccess();
+ if (record->getFilterId() != 0) {
+ asyncUnsetInterestFilter(record->getFilterId());
}
+
+ NDN_LOG_INFO("unregistering prefix: " << record->getPrefix());
+ m_face.m_nfdController->start<nfd::RibUnregisterCommand>(
+ nfd::ControlParameters().setName(record->getPrefix()),
+ [=] (const nfd::ControlParameters&) {
+ NDN_LOG_INFO("unregistered prefix: " << record->getPrefix());
+ m_registeredPrefixTable.erase(id);
+
+ if (onSuccess != nullptr) {
+ onSuccess();
+ }
+ },
+ [=] (const nfd::ControlResponse& resp) {
+ NDN_LOG_INFO("unregister prefix failed: " << record->getPrefix());
+ onFailure(resp.getText());
+ },
+ record->getCommandOptions());
}
public: // IO routine
@@ -427,7 +377,6 @@
Scheduler m_scheduler;
scheduler::ScopedEventId m_processEventsTimeoutEvent;
- std::atomic_uintptr_t m_lastPendingInterestId;
PendingInterestTable m_pendingInterestTable;
InterestFilterTable m_interestFilterTable;
RegisteredPrefixTable m_registeredPrefixTable;
diff --git a/ndn-cxx/impl/interest-filter-record.hpp b/ndn-cxx/impl/interest-filter-record.hpp
index a8c7a81..e3c7ea6 100644
--- a/ndn-cxx/impl/interest-filter-record.hpp
+++ b/ndn-cxx/impl/interest-filter-record.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.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -27,9 +27,16 @@
namespace ndn {
/**
+ * @brief Opaque type to identify an InterestFilterRecord
+ */
+class InterestFilterId;
+
+static_assert(sizeof(const InterestFilterId*) == sizeof(RecordId), "");
+
+/**
* @brief associates an InterestFilter with Interest callback
*/
-class InterestFilterRecord : noncopyable
+class InterestFilterRecord : public RecordBase<InterestFilterRecord>
{
public:
/**
@@ -45,9 +52,6 @@
{
}
- /**
- * @return the filter
- */
const InterestFilter&
getFilter() const
{
@@ -82,33 +86,6 @@
InterestCallback m_interestCallback;
};
-/**
- * @brief Opaque type to identify an InterestFilterRecord
- */
-class InterestFilterId;
-
-/**
- * @brief Functor to match InterestFilterId
- */
-class MatchInterestFilterId
-{
-public:
- explicit
- MatchInterestFilterId(const InterestFilterId* interestFilterId)
- : m_id(interestFilterId)
- {
- }
-
- bool
- operator()(const shared_ptr<InterestFilterRecord>& interestFilterId) const
- {
- return reinterpret_cast<const InterestFilterId*>(interestFilterId.get()) == m_id;
- }
-
-private:
- const InterestFilterId* m_id;
-};
-
} // namespace ndn
#endif // NDN_IMPL_INTEREST_FILTER_RECORD_HPP
diff --git a/ndn-cxx/impl/pending-interest.hpp b/ndn-cxx/impl/pending-interest.hpp
index a41934e..15cedbc 100644
--- a/ndn-cxx/impl/pending-interest.hpp
+++ b/ndn-cxx/impl/pending-interest.hpp
@@ -25,6 +25,7 @@
#include "ndn-cxx/data.hpp"
#include "ndn-cxx/face.hpp"
#include "ndn-cxx/interest.hpp"
+#include "ndn-cxx/impl/record-container.hpp"
#include "ndn-cxx/lp/nack.hpp"
#include "ndn-cxx/util/scheduler.hpp"
@@ -35,6 +36,8 @@
*/
class PendingInterestId;
+static_assert(sizeof(const PendingInterestId*) == sizeof(RecordId), "");
+
/**
* @brief Indicates where a pending Interest came from
*/
@@ -60,7 +63,7 @@
/**
* @brief Stores a pending Interest and associated callbacks
*/
-class PendingInterest : noncopyable
+class PendingInterest : public RecordBase<PendingInterest>
{
public:
/**
@@ -69,14 +72,10 @@
* The timeout is set based on the current time and InterestLifetime.
* This class will invoke the timeout callback unless the record is deleted before timeout.
*/
- PendingInterest(const PendingInterestId* id,
- shared_ptr<const Interest> interest,
- const DataCallback& dataCallback,
- const NackCallback& nackCallback,
- const TimeoutCallback& timeoutCallback,
+ PendingInterest(shared_ptr<const Interest> interest, const DataCallback& dataCallback,
+ const NackCallback& nackCallback, const TimeoutCallback& timeoutCallback,
Scheduler& scheduler)
- : m_id(id)
- , m_interest(std::move(interest))
+ : m_interest(std::move(interest))
, m_origin(PendingInterestOrigin::APP)
, m_dataCallback(dataCallback)
, m_nackCallback(nackCallback)
@@ -88,25 +87,15 @@
/**
* @brief Construct a pending Interest record for an Interest from NFD
- *
- * @param interest the Interest
- * @param scheduler Scheduler for scheduling the timeout event
*/
PendingInterest(shared_ptr<const Interest> interest, Scheduler& scheduler)
- : m_id(nullptr)
- , m_interest(std::move(interest))
+ : m_interest(std::move(interest))
, m_origin(PendingInterestOrigin::FORWARDER)
, m_nNotNacked(0)
{
scheduleTimeoutEvent(scheduler);
}
- const PendingInterestId*
- getId() const
- {
- return m_id;
- }
-
shared_ptr<const Interest>
getInterest() const
{
@@ -172,15 +161,6 @@
}
}
- /**
- * @brief Set cleanup function to be invoked when Interest times out
- */
- void
- setDeleter(const std::function<void()>& deleter)
- {
- m_deleter = deleter;
- }
-
private:
void
scheduleTimeoutEvent(Scheduler& scheduler)
@@ -199,12 +179,10 @@
m_timeoutCallback(*m_interest);
}
- BOOST_ASSERT(m_deleter);
- m_deleter();
+ deleteSelf();
}
private:
- const PendingInterestId* m_id;
shared_ptr<const Interest> m_interest;
PendingInterestOrigin m_origin;
DataCallback m_dataCallback;
@@ -216,28 +194,6 @@
std::function<void()> m_deleter;
};
-/**
- * @brief Functor to match PendingInterestId
- */
-class MatchPendingInterestId
-{
-public:
- explicit
- MatchPendingInterestId(const PendingInterestId* pendingInterestId)
- : m_id(pendingInterestId)
- {
- }
-
- bool
- operator()(const shared_ptr<const PendingInterest>& pendingInterest) const
- {
- return pendingInterest->getId() == m_id;
- }
-
-private:
- const PendingInterestId* m_id;
-};
-
} // namespace ndn
#endif // NDN_IMPL_PENDING_INTEREST_HPP
diff --git a/ndn-cxx/impl/record-container.hpp b/ndn-cxx/impl/record-container.hpp
new file mode 100644
index 0000000..d488393
--- /dev/null
+++ b/ndn-cxx/impl/record-container.hpp
@@ -0,0 +1,199 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2013-2019 Regents of the University of California.
+ *
+ * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
+ *
+ * ndn-cxx library is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later version.
+ *
+ * ndn-cxx library 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 Lesser General Public License for more details.
+ *
+ * You should have received copies of the GNU General Public License and GNU Lesser
+ * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
+ */
+
+#ifndef NDN_IMPL_RECORD_CONTAINER_HPP
+#define NDN_IMPL_RECORD_CONTAINER_HPP
+
+#include "ndn-cxx/detail/common.hpp"
+#include "ndn-cxx/util/signal.hpp"
+
+#include <atomic>
+
+namespace ndn {
+
+using RecordId = uintptr_t;
+
+template<typename T>
+class RecordContainer;
+
+/** \brief Template of PendingInterest, RegisteredPrefix, and InterestFilterRecord.
+ * \tparam T concrete type
+ */
+template<typename T>
+class RecordBase : noncopyable
+{
+public:
+ RecordId
+ getId() const
+ {
+ BOOST_ASSERT(m_id != 0);
+ return m_id;
+ }
+
+protected:
+ ~RecordBase() = default;
+
+ /** \brief Delete this record from the container.
+ */
+ void
+ deleteSelf()
+ {
+ BOOST_ASSERT(m_container != nullptr);
+ m_container->erase(m_id);
+ }
+
+private:
+ RecordContainer<T>* m_container = nullptr;
+ RecordId m_id = 0;
+ friend RecordContainer<T>;
+};
+
+/** \brief Container of PendingInterest, RegisteredPrefix, or InterestFilterRecord.
+ * \tparam T record type
+ */
+template<typename T>
+class RecordContainer
+{
+public:
+ using Record = T;
+ using Container = std::map<RecordId, Record>;
+
+ /** \brief Retrieve record by ID.
+ */
+ Record*
+ get(RecordId id)
+ {
+ auto i = m_container.find(id);
+ if (i == m_container.end()) {
+ return nullptr;
+ }
+ return &i->second;
+ }
+
+ /** \brief Insert a record with given ID.
+ */
+ template<typename ...TArgs>
+ Record&
+ put(RecordId id, TArgs&&... args)
+ {
+ BOOST_ASSERT(id != 0);
+ auto it = m_container.emplace(std::piecewise_construct, std::forward_as_tuple(id),
+ std::forward_as_tuple(std::forward<decltype(args)>(args)...));
+ BOOST_ASSERT(it.second);
+
+ Record& record = it.first->second;
+ record.m_container = this;
+ record.m_id = id;
+ return record;
+ }
+
+ RecordId
+ allocateId()
+ {
+ return ++m_lastId;
+ }
+
+ /** \brief Insert a record with newly assigned ID.
+ */
+ template<typename ...TArgs>
+ Record&
+ insert(TArgs&&... args)
+ {
+ return put(allocateId(), std::forward<decltype(args)>(args)...);
+ }
+
+ void
+ erase(RecordId id)
+ {
+ m_container.erase(id);
+ if (empty()) {
+ this->onEmpty();
+ }
+ }
+
+ void
+ clear()
+ {
+ m_container.clear();
+ this->onEmpty();
+ }
+
+ /** \brief Visit all records with the option to erase.
+ * \tparam Visitor function of type 'bool f(Record& record)'
+ * \param f visitor function, return true to erase record
+ */
+ template<typename Visitor>
+ void
+ removeIf(const Visitor& f)
+ {
+ for (auto i = m_container.begin(); i != m_container.end(); ) {
+ bool wantErase = f(i->second);
+ if (wantErase) {
+ i = m_container.erase(i);
+ }
+ else {
+ ++i;
+ }
+ }
+ if (empty()) {
+ this->onEmpty();
+ }
+ }
+
+ /** \brief Visit all records.
+ * \tparam Visitor function of type 'void f(Record& record)'
+ * \param f visitor function
+ */
+ template<typename Visitor>
+ void
+ forEach(const Visitor& f)
+ {
+ removeIf([&f] (Record& record) {
+ f(record);
+ return false;
+ });
+ }
+
+ bool
+ empty() const noexcept
+ {
+ return m_container.empty();
+ }
+
+ size_t
+ size() const noexcept
+ {
+ return m_container.size();
+ }
+
+public:
+ /** \brief Signals when container becomes empty
+ */
+ util::Signal<RecordContainer<T>> onEmpty;
+
+private:
+ Container m_container;
+ std::atomic<RecordId> m_lastId{0};
+};
+
+} // namespace ndn
+
+#endif // NDN_IMPL_RECORD_CONTAINER_HPP
diff --git a/ndn-cxx/impl/registered-prefix.hpp b/ndn-cxx/impl/registered-prefix.hpp
index dce512b..423aec1 100644
--- a/ndn-cxx/impl/registered-prefix.hpp
+++ b/ndn-cxx/impl/registered-prefix.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.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
@@ -22,7 +22,6 @@
#ifndef NDN_IMPL_REGISTERED_PREFIX_HPP
#define NDN_IMPL_REGISTERED_PREFIX_HPP
-#include "ndn-cxx/interest.hpp"
#include "ndn-cxx/impl/interest-filter-record.hpp"
#include "ndn-cxx/mgmt/nfd/command-options.hpp"
#include "ndn-cxx/mgmt/nfd/control-parameters.hpp"
@@ -30,17 +29,23 @@
namespace ndn {
/**
+ * @brief Opaque type to identify a RegisteredPrefix
+ */
+class RegisteredPrefixId;
+
+static_assert(sizeof(const RegisteredPrefixId*) == sizeof(RecordId), "");
+
+/**
* @brief stores information about a prefix registered in NDN forwarder
*/
-class RegisteredPrefix : noncopyable
+class RegisteredPrefix : public RecordBase<RegisteredPrefix>
{
public:
- RegisteredPrefix(const Name& prefix,
- shared_ptr<InterestFilterRecord> filter,
- const nfd::CommandOptions& options)
+ RegisteredPrefix(const Name& prefix, const nfd::CommandOptions& options,
+ RecordId filterId = 0)
: m_prefix(prefix)
- , m_filter(filter)
, m_options(options)
+ , m_filterId(filterId)
{
}
@@ -50,49 +55,22 @@
return m_prefix;
}
- const shared_ptr<InterestFilterRecord>&
- getFilter() const
- {
- return m_filter;
- }
-
const nfd::CommandOptions&
getCommandOptions() const
{
return m_options;
}
+ RecordId
+ getFilterId() const
+ {
+ return m_filterId;
+ }
+
private:
Name m_prefix;
- shared_ptr<InterestFilterRecord> m_filter;
nfd::CommandOptions m_options;
-};
-
-/**
- * @brief Opaque type to identify a RegisteredPrefix
- */
-class RegisteredPrefixId;
-
-/**
- * @brief Functor to match RegisteredPrefixId
- */
-class MatchRegisteredPrefixId
-{
-public:
- explicit
- MatchRegisteredPrefixId(const RegisteredPrefixId* registeredPrefixId)
- : m_id(registeredPrefixId)
- {
- }
-
- bool
- operator()(const shared_ptr<RegisteredPrefix>& registeredPrefix) const
- {
- return reinterpret_cast<const RegisteredPrefixId*>(registeredPrefix.get()) == m_id;
- }
-
-private:
- const RegisteredPrefixId* m_id;
+ RecordId m_filterId;
};
} // namespace ndn