summaryrefslogtreecommitdiffstats
path: root/control/functor.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'control/functor.hpp')
-rw-r--r--control/functor.hpp109
1 files changed, 109 insertions, 0 deletions
diff --git a/control/functor.hpp b/control/functor.hpp
new file mode 100644
index 0000000..f2f3a78
--- /dev/null
+++ b/control/functor.hpp
@@ -0,0 +1,109 @@
+#pragma once
+
+#include "types.hpp"
+#include <phosphor-logging/log.hpp>
+
+namespace phosphor
+{
+namespace fan
+{
+namespace control
+{
+class Zone;
+
+using namespace phosphor::logging;
+
+/**
+ * @brief Create a handler function object
+ *
+ * @param[in] handler - The handler being created
+ *
+ * @return - The created handler function object
+ */
+template <typename T>
+auto make_handler(T&& handler)
+{
+ return Handler(std::forward<T>(handler));
+}
+
+/**
+ * @struct Property Changed
+ * @brief A match filter functor for Dbus property value changed signals
+ *
+ * @tparam T - The type of the property value
+ * @tparam U - The type of the handler
+ */
+template <typename T, typename U>
+struct PropertyChanged
+{
+ PropertyChanged() = delete;
+ ~PropertyChanged() = default;
+ PropertyChanged(const PropertyChanged&) = default;
+ PropertyChanged& operator=(const PropertyChanged&) = default;
+ PropertyChanged(PropertyChanged&&) = default;
+ PropertyChanged& operator=(PropertyChanged&&) = default;
+ PropertyChanged(const char* iface,
+ const char* property,
+ U&& handler) :
+ _iface(iface),
+ _property(property),
+ _handler(std::forward<U>(handler)) { }
+
+ /** @brief Run signal handler function
+ *
+ * Extract the property from the PropertiesChanged
+ * message and run the handler function.
+ */
+ void operator()(sdbusplus::bus::bus&,
+ sdbusplus::message::message& msg,
+ Zone& zone) const
+ {
+ std::map<std::string, sdbusplus::message::variant<T>> properties;
+ const char* iface = nullptr;
+
+ msg.read(iface);
+ if (!iface || strcmp(iface, _iface))
+ {
+ return;
+ }
+
+ msg.read(properties);
+ auto it = properties.find(_property);
+ if (it == properties.cend())
+ {
+ log<level::ERR>("Unable to find property on interface",
+ entry("PROPERTY=%s", _property),
+ entry("INTERFACE=%s", _iface));
+ return;
+ }
+
+ _handler(zone, std::forward<T>(it->second.template get<T>()));
+ }
+
+private:
+ const char* _iface;
+ const char* _property;
+ U _handler;
+};
+
+/**
+ * @brief Used to process a Dbus property changed signal event
+ *
+ * @param[in] iface - Sensor value interface
+ * @param[in] property - Sensor value property
+ * @param[in] handler - Handler function to perform
+ *
+ * @tparam T - The type of the property
+ * @tparam U - The type of the handler
+ */
+template <typename T, typename U>
+auto propertySignal(const char* iface,
+ const char* property,
+ U&& handler)
+{
+ return PropertyChanged<T, U>(iface, property, std::forward<U>(handler));
+}
+
+} // namespace control
+} // namespace fan
+} // namespace phosphor
OpenPOWER on IntegriCloud