asio: Added method add_unique_interface to object_server

Add_unique_interface returns unique_ptr instead of shared_ptr.
When shared_ptr is used call to object_server::remove_interface
is needed, when unique_ptr is used interface is removed when
goes out of scope.

Tested:
  - Changed two of the examples to use this method
  - All other tests are still passing after this change

Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
Change-Id: I490acafdaf0cd62419a0540adbb846c393c3939f
diff --git a/example/get-all-properties.cpp b/example/get-all-properties.cpp
index 7a2d037..fec7f6d 100644
--- a/example/get-all-properties.cpp
+++ b/example/get-all-properties.cpp
@@ -36,7 +36,8 @@
         ioc_(ioc),
         bus_(bus), objServer_(objServer)
     {
-        demo_ = objServer_.add_interface(xyz::demo::path, xyz::demo::interface);
+        demo_ = objServer_.add_unique_interface(xyz::demo::path,
+                                                xyz::demo::interface);
 
         demo_->register_property_r(name::greetings, std::string(),
                                    sdbusplus::vtable::property_::const_,
@@ -58,11 +59,6 @@
         demo_->initialize();
     }
 
-    ~Application()
-    {
-        objServer_.remove_interface(demo_);
-    }
-
     uint32_t fatalErrors() const
     {
         return fatalErrors_;
@@ -194,7 +190,7 @@
     sdbusplus::asio::connection& bus_;
     sdbusplus::asio::object_server& objServer_;
 
-    std::shared_ptr<sdbusplus::asio::dbus_interface> demo_;
+    std::unique_ptr<sdbusplus::asio::dbus_interface> demo_;
     std::string greetings_ = "Hello";
     std::string goodbyes_ = "Bye";
 
diff --git a/example/register-property.cpp b/example/register-property.cpp
index 530a004..1f6a730 100644
--- a/example/register-property.cpp
+++ b/example/register-property.cpp
@@ -73,27 +73,23 @@
         ioc_(ioc),
         bus_(bus), objServer_(objServer)
     {
-        demo_ = objServer_.add_interface(xyz::demo::path, xyz::demo::name);
+        demo_ = objServer_.add_unique_interface(
+            xyz::demo::path, xyz::demo::name,
+            [this](sdbusplus::asio::dbus_interface& demo) {
+                demo.register_property_r(
+                    name::greetings, std::string(),
+                    sdbusplus::vtable::property_::const_,
+                    [this](const auto&) { return greetings_; });
 
-        demo_->register_property_r(name::greetings, std::string(),
-                                   sdbusplus::vtable::property_::const_,
-                                   [this](const auto&) { return greetings_; });
-
-        demo_->register_property_rw(
-            name::goodbyes, std::string(),
-            sdbusplus::vtable::property_::emits_change,
-            [this](const auto& newPropertyValue, const auto&) {
-                goodbyes_ = newPropertyValue;
-                return 1;
-            },
-            [this](const auto&) { return goodbyes_; });
-
-        demo_->initialize();
-    }
-
-    ~Application()
-    {
-        objServer_.remove_interface(demo_);
+                demo.register_property_rw(
+                    name::goodbyes, std::string(),
+                    sdbusplus::vtable::property_::emits_change,
+                    [this](const auto& newPropertyValue, const auto&) {
+                        goodbyes_ = newPropertyValue;
+                        return 1;
+                    },
+                    [this](const auto&) { return goodbyes_; });
+            });
     }
 
     uint32_t fatalErrors() const
@@ -167,12 +163,18 @@
             });
     }
 
+    void syncChangeGoodbyes(std::string_view value)
+    {
+        goodbyes_ = value;
+        demo_->signal_property(name::goodbyes);
+    }
+
   private:
     boost::asio::io_context& ioc_;
     sdbusplus::asio::connection& bus_;
     sdbusplus::asio::object_server& objServer_;
 
-    std::shared_ptr<sdbusplus::asio::dbus_interface> demo_;
+    std::unique_ptr<sdbusplus::asio::dbus_interface> demo_;
     std::string greetings_ = "Hello";
     std::string goodbyes_ = "Bye";
 
@@ -201,6 +203,8 @@
 
     Application app(ioc, *bus, *objServer);
 
+    app.syncChangeGoodbyes("Good bye");
+
     boost::asio::post(ioc,
                       [&app] { app.asyncReadPropertyWithIncorrectType(); });
     boost::asio::post(ioc, [&app] { app.asyncReadProperties(); });
diff --git a/include/sdbusplus/asio/object_server.hpp b/include/sdbusplus/asio/object_server.hpp
index cf3cb80..4fd04c7 100644
--- a/include/sdbusplus/asio/object_server.hpp
+++ b/include/sdbusplus/asio/object_server.hpp
@@ -835,6 +835,31 @@
         return dbusIface;
     }
 
+    std::unique_ptr<dbus_interface>
+        add_unique_interface(const std::string& path, const std::string& name)
+    {
+        return std::make_unique<dbus_interface>(conn_, path, name);
+    }
+
+    /**
+      @brief creates initialized dbus_interface
+      @param path a string path to interface
+      @param name a string name of the interface
+      @param initializer a functor (void (dbus_interface&)) to be called before
+             call to dbus_interface::initialize
+      @return an unique_ptr to initialized dbus_interface
+      */
+    template <class Initializer>
+    std::unique_ptr<dbus_interface>
+        add_unique_interface(const std::string& path, const std::string& name,
+                             Initializer&& initializer)
+    {
+        auto dbusIface = std::make_unique<dbus_interface>(conn_, path, name);
+        initializer(*dbusIface);
+        dbusIface->initialize();
+        return dbusIface;
+    }
+
     void add_manager(const std::string& path)
     {
         managers_.emplace_back(
@@ -842,7 +867,7 @@
                 static_cast<sdbusplus::bus::bus&>(*conn_), path.c_str())));
     }
 
-    bool remove_interface(std::shared_ptr<dbus_interface>& iface)
+    bool remove_interface(const std::shared_ptr<dbus_interface>& iface)
     {
         auto findIface =
             std::find(interfaces_.begin(), interfaces_.end(), iface);