face: Adding new constructors that accept reference to io_service object

Constructors that accept shared_ptr<io_service> are marked deprecated
and will be removed at some point in the future.

Change-Id: I65d5aff79b82a2977fab502e4aab67327a658433
diff --git a/src/face.cpp b/src/face.cpp
index 5e9cd3c..4f89c2e 100644
--- a/src/face.cpp
+++ b/src/face.cpp
@@ -36,6 +36,22 @@
             ioService);
 }
 
+class NullIoDeleter
+{
+public:
+  void
+  operator()(boost::asio::io_service*)
+  {
+  }
+};
+
+Face::Face(boost::asio::io_service& ioService)
+{
+  const std::string socketName = UnixTransport::getDefaultSocketName(m_config);
+  construct(shared_ptr<Transport>(new UnixTransport(socketName)),
+            shared_ptr<boost::asio::io_service>(&ioService, NullIoDeleter()));
+}
+
 Face::Face(const std::string& host, const std::string& port/* = "6363"*/)
 {
   construct(shared_ptr<Transport>(new TcpTransport(host, port)),
@@ -49,9 +65,10 @@
 }
 
 Face::Face(const shared_ptr<Transport>& transport,
-           const shared_ptr<boost::asio::io_service>& ioService)
+           boost::asio::io_service& ioService)
 {
-  construct(transport, ioService);
+  construct(transport,
+            shared_ptr<boost::asio::io_service>(&ioService, NullIoDeleter()));
 }
 
 void
@@ -203,8 +220,10 @@
   shared_ptr<RegisteredPrefix> prefixToRegister(new RegisteredPrefix(prefix, onInterest));
 
   m_fwController->selfRegisterPrefix(prefixToRegister->getPrefix(),
-                                     bind(&RegisteredPrefixTable::push_back, &m_registeredPrefixTable, prefixToRegister),
-                                     bind(onSetInterestFilterFailed, prefixToRegister->getPrefix(), _1));
+                                     bind(&RegisteredPrefixTable::push_back,
+                                          &m_registeredPrefixTable, prefixToRegister),
+                                     bind(onSetInterestFilterFailed,
+                                          prefixToRegister->getPrefix(), _1));
 
   return reinterpret_cast<const RegisteredPrefixId*>(prefixToRegister.get());
 }
@@ -218,7 +237,8 @@
 void
 Face::asyncUnsetInterestFilter(const RegisteredPrefixId* registeredPrefixId)
 {
-  RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(), m_registeredPrefixTable.end(),
+  RegisteredPrefixTable::iterator i = std::find_if(m_registeredPrefixTable.begin(),
+                                                   m_registeredPrefixTable.end(),
                                                    MatchRegisteredPrefixId(registeredPrefixId));
   if (i != m_registeredPrefixTable.end())
     {
@@ -227,7 +247,7 @@
                                            Controller::FailCallback());
     }
 
-  // there cannot be two registered prefixes with the same id. if there are, then something is broken
+  // there cannot be two registered prefixes with the same id
 }
 
 void
@@ -390,7 +410,7 @@
     {
       if ((*i)->getInterest()->matchesData(data))
         {
-          // Copy pointers to the needed objects and remove the PIT entry before the calling the callback.
+          // Copy pointers to the objects and remove the PIT entry before calling the callback.
           OnData onData = (*i)->getOnData();
           shared_ptr<const Interest> interest = (*i)->getInterest();
 
diff --git a/src/face.hpp b/src/face.hpp
index 2920a7d..b45911d 100644
--- a/src/face.hpp
+++ b/src/face.hpp
@@ -65,15 +65,21 @@
   };
 
   /**
-   * @brief Create a new Face for communication with an NDN Forwarder using the default UnixTransport.
+   * @brief Create a new Face using the default transport (UnixTransport)
+   *
    * @throws ConfigFile::Error on configuration file parse failure
    * @throws Face::Error on unsupported protocol
    */
   Face();
 
   /**
-   * @brief Create a new Face for communication with an NDN Forwarder using the default UnixTransport.
-   * @param ioService A shared pointer to boost::io_service object that should control all IO operations
+   * @brief Create a new Face using the default transport (UnixTransport)
+   *
+   * @deprecated This constructor is deprecated.  Use `Face(boost::asio::io_service&)`
+   *             instead.
+   *
+   * @param ioService A shared pointer to boost::io_service object that should control all
+   *                  IO operations
    * @throws ConfigFile::Error on configuration file parse failure
    * @throws Face::Error on unsupported protocol
    */
@@ -81,7 +87,37 @@
   Face(const shared_ptr<boost::asio::io_service>& ioService);
 
   /**
-   * Create a new Face for communication with an NDN hub at host:port using the default TcpTransport.
+   * @brief Create a new Face using the default transport (UnixTransport)
+   *
+   * @par Usage examples:
+   *
+   *     Face face1;
+   *     Face face2(face1.getIoService());
+   *
+   *     // Now the following ensures that events on both faces are processed
+   *     face1.processEvents();
+   *     // or face1.getIoService().run();
+   *
+   * @par or
+   *
+   *     boost::asio::io_service ioService;
+   *     Face face1(ioService);
+   *     Face face2(ioService);
+   *     ...
+   *
+   *     ioService.run();
+   *
+   * @param ioService A reference to boost::io_service object that should control all
+   *                  IO operations.
+   * @throws ConfigFile::Error on configuration file parse failure
+   * @throws Face::Error on unsupported protocol
+   */
+  explicit
+  Face(boost::asio::io_service& ioService);
+
+  /**
+   * @brief Create a new Face using TcpTransport
+   *
    * @param host The host of the NDN hub.
    * @param port The port or service name of the NDN hub. If omitted. use 6363.
    * @throws Face::Error on unsupported protocol
@@ -89,29 +125,22 @@
   Face(const std::string& host, const std::string& port = "6363");
 
   /**
-   * Create a new Face for communication with an NDN hub with the given Transport object and connectionInfo.
+   * @brief Create a new Face using the given Transport
    * @param transport A shared_ptr to a Transport object used for communication.
-   * @param transport A shared_ptr to a Transport::ConnectionInfo to be used to connect to the transport.
    * @throws Face::Error on unsupported protocol
    */
   explicit
   Face(const shared_ptr<Transport>& transport);
 
   /**
-   * @brief Alternative (special use case) version of the constructor, can be used to aggregate
-   *        several Faces within one processing thread
+   * @brief Create a new Face using the given Transport and IO service object
    *
-   * <code>
-   *     Face face1(...);
-   *     Face face2(..., face1.getAsyncService());
+   * @sa Face(boost::asio::io_service&)
    *
-   *     // Now the following ensures that events on both faces are processed
-   *     face1.processEvents();
-   * </code>
    * @throws Face::Error on unsupported protocol
    */
   Face(const shared_ptr<Transport>& transport,
-       const shared_ptr<boost::asio::io_service>& ioService);
+       boost::asio::io_service& ioService);
 
   /**
    * @brief Set controller used for prefix registration
@@ -150,22 +179,32 @@
                   const OnData& onData, const OnTimeout& onTimeout = OnTimeout());
 
   /**
-   * Remove the pending interest entry with the pendingInterestId from the pending interest table.
-   * This does not affect another pending interest with a different pendingInterestId, even it if has the same interest name.
-   * If there is no entry with the pendingInterestId, do nothing.
+   * @brief Remove the pending interest entry with the pendingInterestId from the pending
+   * interest table.
+   *
+   * This does not affect another pending interest with a different pendingInterestId,
+   * even it if has the same interest name.  If there is no entry with the
+   * pendingInterestId, do nothing.
+   *
    * @param pendingInterestId The ID returned from expressInterest.
    */
   void
   removePendingInterest(const PendingInterestId* pendingInterestId);
 
   /**
-   * Register prefix with the connected NDN hub and call onInterest when a matching interest is received.
-   * @param prefix A reference to a Name for the prefix to register.  This copies the Name.
-   * @param onInterest A function object to call when a matching interest is received.  This copies the function object, so you may need to
-   * use ref() as appropriate.
-   * @param onRegisterFailed A function object to call if failed to retrieve the connected hub’s ID or failed to register the prefix.
-   * This calls onRegisterFailed(prefix) where prefix is the prefix given to registerPrefix.
-   * @param flags The flags for finer control of which interests are forward to the application.
+   * @brief Register prefix with the connected NDN hub and call onInterest when a matching
+   *        interest is received.
+   *
+   * @param prefix     A reference to a Name for the prefix to register
+   * @param onInterest A function object to call when a matching interest is received
+   *
+   * @param onRegisterFailed A function object to call if failed to retrieve the connected
+   *                         hub’s ID or failed to register the prefix.  This calls
+   *                         onRegisterFailed(prefix) where prefix is the prefix given to
+   *                         registerPrefix.
+   *
+   * @param flags      The flags for finer control of which interests are forward to the
+   *                   application.
    * @return The registered prefix ID which can be used with removeRegisteredPrefix.
    */
   const RegisteredPrefixId*
@@ -174,9 +213,13 @@
                     const OnSetInterestFilterFailed& onSetInterestFilterFailed);
 
   /**
-   * Remove the registered prefix entry with the registeredPrefixId from the pending interest table.
-   * 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.
+   * @brief Remove the registered prefix entry with the registeredPrefixId from the
+   *        pending interest table.
+   *
+   * 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.
+   *
    * @param registeredPrefixId The ID returned from registerPrefix.
    */
   void
@@ -185,37 +228,67 @@
    /**
    * @brief Publish data packet
    *
-   * This method can be called to satisfy the incoming Interest or to put Data packet into the cache
-   * of the local NDN forwarder
+   * This method can be called to satisfy the incoming Interest or to put Data packet into
+   * the cache of the local NDN forwarder
    */
   void
   put(const Data& data);
 
   /**
-   * Process any data to receive or call timeout callbacks.
+   * @brief Process any data to receive or call timeout callbacks.
    *
    * This call will block forever (default timeout == 0) to process IO on the face.
    * To exit, one expected to call face.shutdown() from one of the callback methods.
    *
-   * If positive timeout is specified, then processEvents will exit after this timeout,
-   * if not stopped earlier with face.shutdown() or when all active events finish.
-   * The call can be called repeatedly, if desired.
+   * If positive timeout is specified, then processEvents will exit after this timeout, if
+   * not stopped earlier with face.shutdown() or when all active events finish.  The call
+   * can be called repeatedly, if desired.
    *
-   * If negative timeout is specified, then processEvents will not block and process only pending
-   * events.
+   * If negative timeout is specified, then processEvents will not block and process only
+   * pending events.
    *
-   * @throw This may throw an exception for reading data or in the callback for processing the data.  If you
-   * call this from an main event loop, you may want to catch and log/disregard all exceptions.
+   * @param timeout     maximum time to block the thread.
+   * @param keepThread  Keep thread in a blocked state (in event processing), even when
+   *                    there are no outstanding events (e.g., no Interest/Data is expected)
+   *
+   * @throw This may throw an exception for reading data or in the callback for processing
+   * the data.  If you call this from an main event loop, you may want to catch and
+   * log/disregard all exceptions.
    */
   void
   processEvents(const time::milliseconds& timeout = time::milliseconds::zero(),
                 bool keepThread = false);
 
+  /**
+   * @brief Shutdown face operations
+   *
+   * This method cancels all pending operations and closes connection to NDN Forwarder.
+   *
+   * Note that this method does not stop IO service and if the same IO service is shared
+   * between multiple Faces or with other IO objects (e.g., Scheduler).
+   */
   void
   shutdown();
 
+  /**
+   * @brief Get shared_ptr of the IO service object
+   *
+   * @deprecated Use getIoService instead
+   */
   shared_ptr<boost::asio::io_service>
-  ioService() { return m_ioService; }
+  ioService()
+  {
+    return m_ioService;
+  }
+
+  /**
+   * @brief Get reference to IO service object
+   */
+  boost::asio::io_service&
+  getIoService()
+  {
+    return *m_ioService;
+  }
 
 private:
 
@@ -235,7 +308,10 @@
   bool
   isSupportedNdndProtocol(const std::string& protocol);
 
-  struct ProcessEventsTimeout {};
+  class ProcessEventsTimeout
+  {
+  };
+
   typedef std::list<shared_ptr<PendingInterest> > PendingInterestTable;
   typedef std::list<shared_ptr<RegisteredPrefix> > RegisteredPrefixTable;
 
@@ -272,7 +348,7 @@
 
 private:
   shared_ptr<boost::asio::io_service> m_ioService;
-  shared_ptr<boost::asio::io_service::work> m_ioServiceWork; // needed if thread needs to be preserved
+  shared_ptr<boost::asio::io_service::work> m_ioServiceWork; // if thread needs to be preserved
   shared_ptr<monotonic_deadline_timer> m_pitTimeoutCheckTimer;
   bool m_pitTimeoutCheckTimerActive;
   shared_ptr<monotonic_deadline_timer> m_processEventsTimeoutTimer;