Added flags parameter to register_property method
- flags parameter is set by default to vtable::property_::emits_change
- with this change user can set parameter to vtable::property_::none
to avoid sending property change signal for greater performance
- added example/register-property.cpp with example application
which uses new functions
Tested:
- run openbmc tests with this change, no regression detected
- tested that default behaviour (property_::emits_change) is working as intended
- tested that properties still signal change when emit_change flag is used
- tested that properties doesn't signal change when no emit_change flag is used
- tested that const flag is passed and handled corretly
- verified that performance of application increases when emit_change flag turned off
Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
Change-Id: If6187cf076b8e05a5211c83797374a3be94da0c9
diff --git a/example/register-property.cpp b/example/register-property.cpp
new file mode 100644
index 0000000..651e974
--- /dev/null
+++ b/example/register-property.cpp
@@ -0,0 +1,189 @@
+#include <boost/asio.hpp>
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+#include <sdbusplus/bus.hpp>
+
+#include <iostream>
+
+namespace xyz
+{
+namespace demo
+{
+
+const std::string path = "/xyz/demo";
+const std::string name = "xyz.demo";
+
+} // namespace demo
+} // namespace xyz
+
+namespace name
+{
+
+const std::string greetings = "Greetings";
+const std::string goodbyes = "Goodbyes";
+
+} // namespace name
+
+namespace utils
+{
+
+template <class T>
+class Property
+{
+ public:
+ Property(sdbusplus::asio::connection& bus, std::string_view service,
+ std::string_view path, std::string_view interface,
+ std::string_view name) :
+ bus_(bus),
+ service_(service), path_(path), interface_(interface), name_(name)
+ {}
+
+ template <class F>
+ void async_get(F&& callback)
+ {
+ bus_.async_method_call(
+ [callback =
+ std::move(callback)](const boost::system::error_code& error,
+ const std::variant<T>& valueVariant) {
+ if (error)
+ {
+ callback(std::nullopt);
+ return;
+ }
+
+ if (auto value = std::get_if<T>(&valueVariant))
+ {
+ callback(*value);
+ return;
+ }
+
+ callback(std::nullopt);
+ },
+ service_, path_, "org.freedesktop.DBus.Properties", "Get",
+ interface_, name_);
+ }
+
+ template <class F>
+ void async_set(const T& value, F&& callback)
+ {
+ bus_.async_method_call(
+ [callback = std::move(callback)](
+ const boost::system::error_code& error) { callback(error); },
+ service_, path_, "org.freedesktop.DBus.Properties", "Set",
+ interface_, name_, value);
+ }
+
+ private:
+ sdbusplus::asio::connection& bus_;
+ std::string service_;
+ std::string path_;
+ std::string interface_;
+ std::string name_;
+};
+
+} // namespace utils
+
+class Application
+{
+ public:
+ Application(boost::asio::io_context& ioc, sdbusplus::asio::connection& bus,
+ sdbusplus::asio::object_server& objServer) :
+ ioc_(ioc),
+ bus_(bus), objServer_(objServer)
+ {
+ demo_ = objServer_.add_interface(xyz::demo::path, xyz::demo::name);
+
+ 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_);
+ }
+
+ void asyncReadProperties()
+ {
+ propertyGreetings.async_get([](std::optional<std::string> value) {
+ std::cout << "Greetings value is: "
+ << value.value_or("std::nullopt") << "\n";
+ });
+
+ propertyGoodbyes.async_get([](std::optional<std::string> value) {
+ std::cout << "Goodbyes value is: " << value.value_or("std::nullopt")
+ << "\n";
+ });
+ }
+
+ void asyncChangeProperty()
+ {
+ propertyGreetings.async_set(
+ "Hi, hey, hello", [](const boost::system::error_code& error) {
+ if (error)
+ {
+ std::cout
+ << "As expected, failed to set greetings property\n";
+ }
+ });
+
+ propertyGoodbyes.async_set(
+ "Bye bye", [this](const boost::system::error_code& error) {
+ if (!error)
+ {
+ std::cout << "Changed goodbyes property as expected\n";
+ }
+ boost::asio::post(ioc_, [this] { asyncReadProperties(); });
+ });
+ }
+
+ private:
+ boost::asio::io_context& ioc_;
+ sdbusplus::asio::connection& bus_;
+ sdbusplus::asio::object_server& objServer_;
+
+ std::shared_ptr<sdbusplus::asio::dbus_interface> demo_;
+ std::string greetings_ = "Hello";
+ std::string goodbyes_ = "Bye";
+
+ utils::Property<std::string> propertyGreetings{
+ bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
+ name::greetings};
+ utils::Property<std::string> propertyGoodbyes{
+ bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
+ name::goodbyes};
+};
+
+int main(int, char**)
+{
+ boost::asio::io_context ioc;
+ boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);
+
+ signals.async_wait(
+ [&ioc](const boost::system::error_code&, const int&) { ioc.stop(); });
+
+ auto bus = std::make_shared<sdbusplus::asio::connection>(ioc);
+ auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus);
+
+ bus->request_name(xyz::demo::name.c_str());
+
+ Application app(ioc, *bus, *objServer);
+
+ boost::asio::post(ioc, [&app] { app.asyncReadProperties(); });
+ boost::asio::post(ioc, [&app] { app.asyncChangeProperty(); });
+
+ ioc.run();
+
+ return 0;
+}