asio: Added utility functions getProperty and setProperty
Tested:
- Modified one of the examples to use this utility instead
- All other tests are still passing after this change
Change-Id: I3237e281915c7edf931e3326b88bd24714ee8ecb
Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
diff --git a/example/get-all-properties.cpp b/example/get-all-properties.cpp
index 8e7ee54..7a2d037 100644
--- a/example/get-all-properties.cpp
+++ b/example/get-all-properties.cpp
@@ -1,7 +1,7 @@
#include <boost/asio.hpp>
#include <sdbusplus/asio/connection.hpp>
-#include <sdbusplus/asio/get_all_properties.hpp>
#include <sdbusplus/asio/object_server.hpp>
+#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/unpack_properties.hpp>
diff --git a/example/register-property.cpp b/example/register-property.cpp
index 651e974..530a004 100644
--- a/example/register-property.cpp
+++ b/example/register-property.cpp
@@ -1,6 +1,7 @@
#include <boost/asio.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
+#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/bus.hpp>
#include <iostream>
@@ -38,39 +39,20 @@
service_(service), path_(path), interface_(interface), name_(name)
{}
- template <class F>
- void async_get(F&& callback)
+ template <class OnError, class OnSuccess>
+ void async_get(OnError&& onError, OnSuccess&& onSuccess)
{
- 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_);
+ sdbusplus::asio::getProperty<T>(bus_, service_, path_, interface_,
+ name_, std::forward<OnError>(onError),
+ std::forward<OnSuccess>(onSuccess));
}
- template <class F>
- void async_set(const T& value, F&& callback)
+ template <class OnError, class OnSuccess>
+ void async_set(T&& value, OnError&& onError, OnSuccess&& onSuccess)
{
- 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);
+ sdbusplus::asio::setProperty(
+ bus_, service_, path_, interface_, name_, std::forward<T>(value),
+ std::forward<OnError>(onError), std::forward<OnSuccess>(onSuccess));
}
private:
@@ -114,36 +96,73 @@
objServer_.remove_interface(demo_);
}
+ uint32_t fatalErrors() const
+ {
+ return fatalErrors_;
+ }
+
+ auto getFailed()
+ {
+ return [this](boost::system::error_code error) {
+ std::cerr << "Error: getProperty failed " << error << "\n";
+ ++fatalErrors_;
+ };
+ }
+
+ void asyncReadPropertyWithIncorrectType()
+ {
+ utils::Property<uint32_t> propertyWithWrongType{
+ bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
+ name::greetings};
+
+ propertyWithWrongType.async_get(
+ [](boost::system::error_code error) {
+ std::cout
+ << "As expected failed to getProperty with wrong type: "
+ << error << "\n";
+ },
+ [this](uint32_t) {
+ std::cerr << "Error: it was expected to fail getProperty due "
+ "to wrong type\n";
+ ++fatalErrors_;
+ });
+ }
+
void asyncReadProperties()
{
- propertyGreetings.async_get([](std::optional<std::string> value) {
- std::cout << "Greetings value is: "
- << value.value_or("std::nullopt") << "\n";
+ propertyGreetings.async_get(getFailed(), [](std::string value) {
+ std::cout << "Greetings value is: " << value << "\n";
});
- propertyGoodbyes.async_get([](std::optional<std::string> value) {
- std::cout << "Goodbyes value is: " << value.value_or("std::nullopt")
- << "\n";
+ propertyGoodbyes.async_get(getFailed(), [](std::string value) {
+ std::cout << "Goodbyes value is: " << value << "\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";
- }
+ "Hi, hey, hello",
+ [](const boost::system::error_code& error) {
+ std::cout << "As expected, failed to set greetings property: "
+ << error << "\n";
+ },
+ [this]() {
+ std::cout
+ << "Error: it was expected to fail to change greetings\n";
+ ++fatalErrors_;
});
propertyGoodbyes.async_set(
- "Bye bye", [this](const boost::system::error_code& error) {
- if (!error)
- {
- std::cout << "Changed goodbyes property as expected\n";
- }
+ "Bye bye",
+ [this](const boost::system::error_code& error) {
+ std::cout << "Error: it supposed to be ok to change goodbyes "
+ "property: "
+ << error << "\n";
+ ++fatalErrors_;
+ },
+ [this]() {
+ std::cout << "Changed goodbyes property as expected\n";
boost::asio::post(ioc_, [this] { asyncReadProperties(); });
});
}
@@ -157,6 +176,8 @@
std::string greetings_ = "Hello";
std::string goodbyes_ = "Bye";
+ uint32_t fatalErrors_ = 0u;
+
utils::Property<std::string> propertyGreetings{
bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
name::greetings};
@@ -180,10 +201,14 @@
Application app(ioc, *bus, *objServer);
+ boost::asio::post(ioc,
+ [&app] { app.asyncReadPropertyWithIncorrectType(); });
boost::asio::post(ioc, [&app] { app.asyncReadProperties(); });
boost::asio::post(ioc, [&app] { app.asyncChangeProperty(); });
ioc.run();
- return 0;
+ std::cout << "Fatal errors count: " << app.fatalErrors() << "\n";
+
+ return app.fatalErrors();
}
diff --git a/include/sdbusplus/asio/get_all_properties.hpp b/include/sdbusplus/asio/get_all_properties.hpp
deleted file mode 100644
index 6bc41fe..0000000
--- a/include/sdbusplus/asio/get_all_properties.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#pragma once
-
-#include <sdbusplus/asio/connection.hpp>
-
-namespace sdbusplus::asio
-{
-
-template <typename OnError, typename OnSuccess>
-inline void getAllProperties(sdbusplus::asio::connection& bus,
- const std::string& service,
- const std::string& path,
- const std::string& interface, OnError&& onError,
- OnSuccess&& onSuccess)
-{
- using FunctionTuple = boost::callable_traits::args_t<OnSuccess>;
- using FunctionTupleType =
- typename sdbusplus::utility::decay_tuple<FunctionTuple>::type;
-
- bus.async_method_call(
- [onError = std::move(onError), onSuccess = std::move(onSuccess)](
- boost::system::error_code ec,
- std::tuple_element_t<0, FunctionTupleType>& ret) {
- if (ec)
- {
- onError(ec);
- return;
- }
-
- onSuccess(ret);
- },
- service, path, "org.freedesktop.DBus.Properties", "GetAll", interface);
-}
-
-} // namespace sdbusplus::asio
diff --git a/include/sdbusplus/asio/property.hpp b/include/sdbusplus/asio/property.hpp
new file mode 100644
index 0000000..94a5820
--- /dev/null
+++ b/include/sdbusplus/asio/property.hpp
@@ -0,0 +1,86 @@
+#pragma once
+
+#include <sdbusplus/asio/connection.hpp>
+
+namespace sdbusplus::asio
+{
+
+template <typename OnError, typename OnSuccess>
+inline void getAllProperties(sdbusplus::asio::connection& bus,
+ const std::string& service,
+ const std::string& path,
+ const std::string& interface, OnError&& onError,
+ OnSuccess&& onSuccess)
+{
+ using FunctionTuple = boost::callable_traits::args_t<OnSuccess>;
+ using FunctionTupleType =
+ typename sdbusplus::utility::decay_tuple<FunctionTuple>::type;
+
+ bus.async_method_call(
+ [onError = std::move(onError), onSuccess = std::move(onSuccess)](
+ boost::system::error_code ec,
+ std::tuple_element_t<0, FunctionTupleType>& ret) {
+ if (ec)
+ {
+ onError(ec);
+ return;
+ }
+
+ onSuccess(ret);
+ },
+ service, path, "org.freedesktop.DBus.Properties", "GetAll", interface);
+}
+
+template <typename T, typename OnError, typename OnSuccess>
+inline void getProperty(sdbusplus::asio::connection& bus,
+ const std::string& service, const std::string& path,
+ const std::string& interface,
+ const std::string& propertyName, OnError&& onError,
+ OnSuccess&& onSuccess)
+{
+ bus.async_method_call(
+ [onError = std::move(onError), onSuccess = std::move(onSuccess)](
+ boost::system::error_code ec,
+ std::variant<std::monostate, T>& ret) {
+ if (ec)
+ {
+ onError(ec);
+ return;
+ }
+
+ if (T* value = std::get_if<T>(&ret))
+ {
+ onSuccess(*value);
+ return;
+ }
+
+ onError(boost::system::errc::make_error_code(
+ boost::system::errc::invalid_argument));
+ },
+ service, path, "org.freedesktop.DBus.Properties", "Get", interface,
+ propertyName);
+}
+
+template <typename T, typename OnError, typename OnSuccess>
+inline void setProperty(sdbusplus::asio::connection& bus,
+ const std::string& service, const std::string& path,
+ const std::string& interface,
+ const std::string& propertyName, T&& propertyValue,
+ OnError&& onError, OnSuccess&& onSuccess)
+{
+ bus.async_method_call(
+ [onError = std::move(onError),
+ onSuccess = std::move(onSuccess)](boost::system::error_code ec) {
+ if (ec)
+ {
+ onError(ec);
+ return;
+ }
+
+ onSuccess();
+ },
+ service, path, "org.freedesktop.DBus.Properties", "Set", interface,
+ propertyName, std::variant<T>(std::forward<T>(propertyValue)));
+}
+
+} // namespace sdbusplus::asio