table: StrategyChoice uses unique_ptr instead of shared_ptr

refs #3164

Change-Id: Id3110f72aab83982b0768e596a04bad9f7336975
diff --git a/daemon/table/strategy-choice.cpp b/daemon/table/strategy-choice.cpp
index 5778237..3c701d4 100644
--- a/daemon/table/strategy-choice.cpp
+++ b/daemon/table/strategy-choice.cpp
@@ -36,11 +36,11 @@
 
 NFD_LOG_INIT("StrategyChoice");
 
-StrategyChoice::StrategyChoice(NameTree& nameTree, shared_ptr<Strategy> defaultStrategy)
+StrategyChoice::StrategyChoice(NameTree& nameTree, unique_ptr<Strategy> defaultStrategy)
   : m_nameTree(nameTree)
   , m_nItems(0)
 {
-  this->setDefaultStrategy(defaultStrategy);
+  this->setDefaultStrategy(std::move(defaultStrategy));
 }
 
 bool
@@ -54,25 +54,27 @@
   }
 }
 
-bool
-StrategyChoice::install(shared_ptr<Strategy> strategy)
+std::pair<bool, Strategy*>
+StrategyChoice::install(unique_ptr<Strategy> strategy)
 {
   BOOST_ASSERT(strategy != nullptr);
-  const Name& strategyName = strategy->getName();
+  Name strategyName = strategy->getName();
+  // copying Name, so that strategyName remains available even if strategy is deallocated
 
-  if (this->hasStrategy(strategyName, true)) {
+  bool isInserted = false;
+  StrategyInstanceTable::iterator it;
+  std::tie(it, isInserted) = m_strategyInstances.emplace(strategyName, std::move(strategy));
+
+  if (!isInserted) {
     NFD_LOG_ERROR("install(" << strategyName << ") duplicate strategyName");
-    return false;
   }
-
-  m_strategyInstances[strategyName] = strategy;
-  return true;
+  return std::make_pair(isInserted, it->second.get());
 }
 
-fw::Strategy*
+Strategy*
 StrategyChoice::getStrategy(const Name& strategyName) const
 {
-  fw::Strategy* candidate = nullptr;
+  Strategy* candidate = nullptr;
   for (auto it = m_strategyInstances.lower_bound(strategyName);
        it != m_strategyInstances.end() && strategyName.isPrefixOf(it->first); ++it) {
     switch (it->first.size() - strategyName.size()) {
@@ -206,19 +208,22 @@
 }
 
 void
-StrategyChoice::setDefaultStrategy(shared_ptr<Strategy> strategy)
+StrategyChoice::setDefaultStrategy(unique_ptr<Strategy> strategy)
 {
-  this->install(strategy);
+  bool isInstalled = false;
+  Strategy* instance = nullptr;
+  std::tie(isInstalled, instance) = this->install(std::move(strategy));
+  BOOST_ASSERT(isInstalled);
 
   auto entry = make_unique<Entry>(Name());
-  entry->setStrategy(*strategy);
+  entry->setStrategy(*instance);
 
   // don't use .insert here, because it will invoke findEffectiveStrategy
   // which expects an existing root entry
   shared_ptr<name_tree::Entry> nte = m_nameTree.lookup(Name());
   nte->setStrategyChoiceEntry(std::move(entry));
   ++m_nItems;
-  NFD_LOG_INFO("setDefaultStrategy " << strategy->getName());
+  NFD_LOG_INFO("setDefaultStrategy " << instance->getName());
 }
 
 static inline void
@@ -241,9 +246,7 @@
 }
 
 void
-StrategyChoice::changeStrategy(Entry& entry,
-                               fw::Strategy& oldStrategy,
-                               fw::Strategy& newStrategy)
+StrategyChoice::changeStrategy(Entry& entry, Strategy& oldStrategy, Strategy& newStrategy)
 {
   if (&oldStrategy == &newStrategy) {
     return;
diff --git a/daemon/table/strategy-choice.hpp b/daemon/table/strategy-choice.hpp
index 7082092..84b1b03 100644
--- a/daemon/table/strategy-choice.hpp
+++ b/daemon/table/strategy-choice.hpp
@@ -46,7 +46,7 @@
 class StrategyChoice : noncopyable
 {
 public:
-  StrategyChoice(NameTree& nameTree, shared_ptr<fw::Strategy> defaultStrategy);
+  StrategyChoice(NameTree& nameTree, unique_ptr<fw::Strategy> defaultStrategy);
 
 public: // available Strategy types
   /** \brief determines if a strategy is installed
@@ -58,11 +58,12 @@
   hasStrategy(const Name& strategyName, bool isExact = false) const;
 
   /** \brief install a strategy
-   *  \return true if installed; false if not installed due to duplicate strategyName
-   *  \note shared_ptr is passed by value because StrategyChoice takes ownership of strategy
+   *  \return if installed, true, and a pointer to the strategy instance;
+   *          if not installed due to duplicate strategyName, false,
+   *          and a pointer to the existing strategy instance
    */
-  bool
-  install(shared_ptr<fw::Strategy> strategy);
+  std::pair<bool, fw::Strategy*>
+  install(unique_ptr<fw::Strategy> strategy);
 
 public: // Strategy Choice table
   /** \brief set strategy of prefix to be strategyName
@@ -92,15 +93,18 @@
   get(const Name& prefix) const;
 
 public: // effective strategy
-  /// get effective strategy for prefix
+  /** \brief get effective strategy for prefix
+   */
   fw::Strategy&
   findEffectiveStrategy(const Name& prefix) const;
 
-  /// get effective strategy for pitEntry
+  /** \brief get effective strategy for pitEntry
+   */
   fw::Strategy&
   findEffectiveStrategy(const pit::Entry& pitEntry) const;
 
-  /// get effective strategy for measurementsEntry
+  /** \brief get effective strategy for measurementsEntry
+   */
   fw::Strategy&
   findEffectiveStrategy(const measurements::Entry& measurementsEntry) const;
 
@@ -136,7 +140,8 @@
     NameTree::const_iterator m_nameTreeIterator;
   };
 
-  /// number of entries stored
+  /** \return number of entries stored
+   */
   size_t
   size() const;
 
@@ -154,7 +159,7 @@
   getStrategy(const Name& strategyName) const;
 
   void
-  setDefaultStrategy(shared_ptr<fw::Strategy> strategy);
+  setDefaultStrategy(unique_ptr<fw::Strategy> strategy);
 
   void
   changeStrategy(Entry& entry,
@@ -168,7 +173,7 @@
   NameTree& m_nameTree;
   size_t m_nItems;
 
-  typedef std::map<Name, shared_ptr<fw::Strategy>> StrategyInstanceTable;
+  typedef std::map<Name, unique_ptr<fw::Strategy>> StrategyInstanceTable;
   StrategyInstanceTable m_strategyInstances;
 };